added available paths

This commit is contained in:
2025-08-28 09:43:42 +05:30
parent 5117e48527
commit a0e5115c6c
9 changed files with 931 additions and 470 deletions

View File

@@ -172,6 +172,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
} }
} }
}); });
const updatePoint = (index: number, pos: THREE.Vector3) => { const updatePoint = (index: number, pos: THREE.Vector3) => {

View File

@@ -29,19 +29,20 @@ export const getPathsByPointId = (pointId: any, paths: PathData) => {
export const setPathPosition = ( export const setPathPosition = (
pointUuid: string, pointUuid: string,
position: [number, number, number], position: [number, number, number],
setPaths: React.Dispatch<React.SetStateAction<PathData>> setPaths: React.Dispatch<React.SetStateAction<PathData>>,
paths: PathData
) => { ) => {
setPaths((prevPaths) => const newPaths = paths.map((path: any) => {
prevPaths.map((path: any) => { if (path?.pathPoints.some((p: any) => p.pointId === pointUuid)) {
if (path?.pathPoints.some((p: any) => p.pointId === pointUuid)) { return {
return { ...path,
...path, pathPoints: path.pathPoints.map((p: any) =>
pathPoints: path.pathPoints.map((p: any) => p.pointId === pointUuid ? { ...p, position } : p
p.pointId === pointUuid ? { ...p, position } : p ) as [PointData, PointData], // 👈 force back to tuple
) as [PointData, PointData], // 👈 force back to tuple };
}; }
} return path;
return path; });
})
); setPaths(newPaths);
}; };

View File

@@ -0,0 +1,46 @@
import { useCallback, useEffect, useMemo } from "react";
import { useCreatedPaths } from "../../../../../store/builder/store";
export const usePathManager = (pathId?: string, vehicleId?: string | null) => {
const { paths, allPaths, setAllPaths } = useCreatedPaths();
console.log("allPaths: ", allPaths);
useEffect(() => {
if (!paths || paths.length === 0) return;
const newPaths = paths.map((val: any) => ({
pathId: val.pathId,
isAvailable: true,
vehicleId: null,
}));
const merged = [...allPaths];
newPaths.forEach((p: any) => {
if (!merged.find((m) => m.pathId === p.pathId)) {
merged.push(p);
}
});
if (merged.length !== allPaths.length) {
setAllPaths(merged);
}
}, [paths, allPaths, setAllPaths]);
useEffect(() => {
if (!pathId || !vehicleId) return;
const updated = allPaths.map((p: any) =>
p.pathId === pathId ? { ...p, vehicleId, isAvailable: false } : p
);
const hasChanged = JSON.stringify(updated) !== JSON.stringify(allPaths);
if (hasChanged) {
setAllPaths(updated);
}
}, [pathId, vehicleId, allPaths, setAllPaths]);
return useMemo(() => {
if (!pathId) return undefined;
return allPaths.find((p: any) => p.pathId === pathId);
}, [pathId, allPaths]);
};

View File

@@ -8,10 +8,9 @@ import React, {
useState, useState,
} from "react"; } from "react";
import { LineCurve3, MathUtils, Plane, Vector3 } from "three"; import { LineCurve3, MathUtils, Plane, Vector3 } from "three";
import { Vector3Array } from "../../../../types/world/worldTypes";
import { import {
useActiveSubTool,
useActiveTool, useActiveTool,
useCreatedPaths,
useToolMode, useToolMode,
} from "../../../../store/builder/store"; } from "../../../../store/builder/store";
import PointHandler from "./pointHandler"; import PointHandler from "./pointHandler";
@@ -36,15 +35,19 @@ interface PathDataInterface {
type PathData = PathDataInterface[]; type PathData = PathDataInterface[];
export default function PathCreator() { export default function PathCreator() {
const [paths, setPaths] = useState<PathData>([]); // const [paths, setPaths] = useState<PathData>([]);
// const [paths, setPaths] = useState<PathData>(() => {
// const stored = localStorage.getItem("paths");
// return stored ? JSON.parse(stored) : [];
// });
const { paths, setPaths } = useCreatedPaths();
const { activeTool } = useActiveTool();
const { toolMode } = useToolMode();
const [draftPoints, setDraftPoints] = useState<PointData[]>([]); const [draftPoints, setDraftPoints] = useState<PointData[]>([]);
const [mousePos, setMousePos] = useState<[number, number, number] | null>( const [mousePos, setMousePos] = useState<[number, number, number] | null>(
null null
); );
const { toolMode } = useToolMode();
const plane = useMemo(() => new Plane(new Vector3(0, 1, 0), 0), []);
const { scene, raycaster, gl } = useThree();
const [snappedPosition, setSnappedPosition] = useState< const [snappedPosition, setSnappedPosition] = useState<
[number, number, number] | null [number, number, number] | null
>(null); >(null);
@@ -54,21 +57,33 @@ export default function PathCreator() {
null null
); );
const [hoveredPoint, setHoveredPoint] = useState<PointData | null>(null); const [hoveredPoint, setHoveredPoint] = useState<PointData | null>(null);
const { activeSubTool } = useActiveSubTool();
const { activeTool } = useActiveTool();
const [pathPointsList, setPathPointsList] = useState<PointData[]>([]); const [pathPointsList, setPathPointsList] = useState<PointData[]>([]);
const [selectedPointIndices, setSelectedPointIndices] = useState<number[]>(
[]
);
const plane = useMemo(() => new Plane(new Vector3(0, 1, 0), 0), []);
const { scene, raycaster, gl } = useThree();
const POINT_SNAP_THRESHOLD = 0.5; const POINT_SNAP_THRESHOLD = 0.5;
const CAN_POINT_SNAP = true; const CAN_POINT_SNAP = true;
useEffect(() => {}, [paths]); useEffect(() => {}, [paths]);
const getAllOtherPathPoints = useCallback((): PointData[] => { const getAllOtherPathPoints = useCallback((): PointData[] => {
if (draftPoints.length === 0) return []; if (draftPoints.length === 0) return [];
return ( return (
paths?.flatMap((path) => paths?.flatMap((path: any) =>
path.pathPoints.filter((pt) => pt.pointId !== draftPoints[0].pointId) path.pathPoints.filter(
(pt: PointData) => pt.pointId !== draftPoints[0].pointId
)
) ?? [] ) ?? []
); );
}, [paths, draftPoints]); }, [paths, draftPoints]);
useEffect(() => {
const stored = localStorage.getItem("paths");
setPaths(stored ? JSON.parse(stored) : []);
}, []);
const snapPathPoint = useCallback( const snapPathPoint = useCallback(
(position: [number, number, number]) => { (position: [number, number, number]) => {
@@ -134,13 +149,11 @@ export default function PathCreator() {
}); });
useEffect(() => {}, [paths]); useEffect(() => {}, [paths]);
const getPathPointById = (uuid: any) => { const getPathPointById = (uuid: any) => {
for (const path of paths) { for (const path of paths) {
const point = path.pathPoints.find((p) => p.pointId === uuid); const point = path.pathPoints.find((p: PointData) => p.pointId === uuid);
console.log(
"point: ",
path.pathPoints.map((val) => val)
);
if (point) return point; if (point) return point;
} }
return undefined; return undefined;
@@ -170,7 +183,9 @@ export default function PathCreator() {
paths paths
); );
if (clickedPath) { if (clickedPath) {
const hitPath = paths.find((p) => p.pathId === clickedPath.pathId); const hitPath = paths.find(
(p: PathDataInterface) => p.pathId === clickedPath.pathId
);
if (!hitPath) return; if (!hitPath) return;
@@ -197,7 +212,13 @@ export default function PathCreator() {
t = Math.max(0, Math.min(1, t)); t = Math.max(0, Math.min(1, t));
const closestPoint = new Vector3().lerpVectors(point1Vec, point2Vec, t); const closestPoint = new Vector3().lerpVectors(point1Vec, point2Vec, t);
setPaths((prev) => prev.filter((p) => p.pathId !== clickedPath.pathId)); const filteredPath = paths.filter(
(p: PathDataInterface) => p.pathId !== clickedPath.pathId
);
setPaths(filteredPath);
// setPaths((prev: PathData) =>
// prev.filter((p) => p.pathId !== clickedPath.pathId)
// );
const point1: PointData = { const point1: PointData = {
pointId: clickedPath?.pathPoints[0].pointId, pointId: clickedPath?.pathPoints[0].pointId,
@@ -222,7 +243,8 @@ export default function PathCreator() {
pathPoints: [point2, splitPoint], pathPoints: [point2, splitPoint],
}; };
setDraftPoints([splitPoint]); setDraftPoints([splitPoint]);
setPaths((prev) => [...prev, path1, path2]);
setPaths([...paths, path1, path2]);
} else { } else {
const newPath: PathDataInterface = { const newPath: PathDataInterface = {
pathId: MathUtils.generateUUID(), pathId: MathUtils.generateUUID(),
@@ -237,7 +259,8 @@ export default function PathCreator() {
pathPoints: [point2, splitPoint], pathPoints: [point2, splitPoint],
}; };
setPaths((prev) => [...prev, newPath, firstPath, secondPath]); setPaths([...paths, newPath, firstPath, secondPath]);
setDraftPoints([splitPoint]); setDraftPoints([splitPoint]);
} }
@@ -287,8 +310,7 @@ export default function PathCreator() {
pathId: MathUtils.generateUUID(), pathId: MathUtils.generateUUID(),
pathPoints: [draftPoints[0], newPoint], pathPoints: [draftPoints[0], newPoint],
}; };
setPaths([...paths, newPath]);
setPaths((prev) => [...prev, newPath]);
setDraftPoints([newPoint]); setDraftPoints([newPoint]);
} }
}; };
@@ -322,7 +344,8 @@ export default function PathCreator() {
const allPoints = useMemo(() => { const allPoints = useMemo(() => {
const points: PointData[] = []; const points: PointData[] = [];
const seen = new Set<string>(); const seen = new Set<string>();
paths.forEach((path) => { console.log("paths: ", paths);
paths?.forEach((path: PathDataInterface) => {
path.pathPoints.forEach((p) => { path.pathPoints.forEach((p) => {
if (!seen.has(p.pointId)) { if (!seen.has(p.pointId)) {
seen.add(p.pointId); seen.add(p.pointId);
@@ -334,8 +357,10 @@ export default function PathCreator() {
}, [paths]); }, [paths]);
useEffect(() => { useEffect(() => {
console.log("allPoints: ", allPoints); console.log("paths ", paths);
localStorage.setItem("paths", JSON.stringify(paths));
}, [paths]); }, [paths]);
return ( return (
<> <>
{/* Draft points (red) */} {/* Draft points (red) */}
@@ -358,6 +383,8 @@ export default function PathCreator() {
setHoveredPoint={setHoveredPoint} setHoveredPoint={setHoveredPoint}
hoveredLine={hoveredLine} hoveredLine={hoveredLine}
hoveredPoint={hoveredPoint} hoveredPoint={hoveredPoint}
selected={selectedPointIndices}
setSelected={setSelectedPointIndices}
/> />
))} ))}
@@ -372,7 +399,7 @@ export default function PathCreator() {
)} )}
{/* Permanent paths */} {/* Permanent paths */}
{paths.map((path) => ( {paths.map((path: PathDataInterface) => (
<PathHandler <PathHandler
key={path.pathId} key={path.pathId}
selectedPath={path} selectedPath={path}

View File

@@ -55,14 +55,17 @@ export default function PathHandler({
const [start, end] = points.map((p) => new Vector3(...p.position)); const [start, end] = points.map((p) => new Vector3(...p.position));
return new LineCurve3(start, end); return new LineCurve3(start, end);
}, [points]); }, [points]);
const removePath = (pathId: string) => { const removePath = (pathId: string) => {
setPaths((prevPaths) => prevPaths.filter((p) => p.pathId !== pathId)); setPaths((prevPaths) => prevPaths.filter((p) => p.pathId !== pathId));
}; };
const handlePathClick = (pointId: string) => { const handlePathClick = (pointId: string) => {
if (toolMode === "3D-Delete") { if (toolMode === "3D-Delete") {
removePath(pointId); removePath(pointId);
} }
}; };
const handleDragStart = (points: [PointData, PointData]) => { const handleDragStart = (points: [PointData, PointData]) => {
if (activeTool !== "cursor") return; if (activeTool !== "cursor") return;
const intersectionPoint = new Vector3(); const intersectionPoint = new Vector3();
@@ -77,6 +80,7 @@ export default function PathHandler({
setInitialPositions({ paths: pathSet }); setInitialPositions({ paths: pathSet });
} }
}; };
// const handleDrag = (points: [PointData, PointData]) => { // const handleDrag = (points: [PointData, PointData]) => {
// if (isHovered && dragOffset) { // if (isHovered && dragOffset) {
// const intersectionPoint = new Vector3(); // const intersectionPoint = new Vector3();
@@ -106,7 +110,7 @@ export default function PathHandler({
// } // }
// } // }
// }; // };
const handleDrag = (points: [PointData, PointData]) => { const handleDrag = (points: [PointData, PointData]) => {
if (isHovered && dragOffset) { if (isHovered && dragOffset) {
const intersectionPoint = new Vector3(); const intersectionPoint = new Vector3();
@@ -135,13 +139,14 @@ export default function PathHandler({
]; ];
// ✅ Move both points separately (wont overwrite other updates) // ✅ Move both points separately (wont overwrite other updates)
setPathPosition(points[0].pointId, newStart, setPaths); setPathPosition(points[0].pointId, newStart, setPaths, paths);
setPathPosition(points[1].pointId, newEnd, setPaths); setPathPosition(points[1].pointId, newEnd, setPaths, paths);
} }
} }
}; };
const handleDragEnd = (points: [PointData, PointData]) => {}; const handleDragEnd = (points: [PointData, PointData]) => {};
return ( return (
<> <>
<DragControls <DragControls

View File

@@ -1,11 +1,27 @@
import { DragControls } from "@react-three/drei"; import { DragControls, Line } from "@react-three/drei";
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, {
import { useActiveTool, useToolMode } from "../../../../store/builder/store"; useCallback,
import { Plane, Vector3 } from "three"; useEffect,
import { useThree } from "@react-three/fiber"; useMemo,
useRef,
useState,
} from "react";
import {
useActiveTool,
useCreatedPaths,
useToolMode,
} from "../../../../store/builder/store";
import { CubicBezierCurve3, Plane, Quaternion, Vector3 } from "three";
import { useFrame, useThree } from "@react-three/fiber";
import { handleCanvasCursors } from "../../../../utils/mouseUtils/handleCanvasCursors"; import { handleCanvasCursors } from "../../../../utils/mouseUtils/handleCanvasCursors";
import { getPathsByPointId, setPathPosition } from "./function/getPaths"; import { getPathsByPointId, setPathPosition } from "./function/getPaths";
import { aStar } from "../structuredPath/functions/aStar"; import { aStar } from "../structuredPath/functions/aStar";
import {
useAnimationPlaySpeed,
usePlayButtonStore,
} from "../../../../store/usePlayButtonStore";
import { useSceneContext } from "../../../scene/sceneContext";
import { usePathManager } from "./function/usePathManager";
type PointData = { type PointData = {
pointId: string; pointId: string;
position: [number, number, number]; position: [number, number, number];
@@ -31,6 +47,8 @@ type PointHandlerProps = {
hoveredLine: PathDataInterface | null; hoveredLine: PathDataInterface | null;
pointIndex: any; pointIndex: any;
points: PointData[]; points: PointData[];
selected: number[];
setSelected: React.Dispatch<React.SetStateAction<number[]>>;
}; };
function dist(a: PointData, b: PointData): number { function dist(a: PointData, b: PointData): number {
return Math.sqrt( return Math.sqrt(
@@ -39,6 +57,13 @@ function dist(a: PointData, b: PointData): number {
(a.position[2] - b.position[2]) ** 2 (a.position[2] - b.position[2]) ** 2
); );
} }
type SegmentPoint = {
position: Vector3;
originalPoint?: PointData;
pathId?: string;
startId?: string;
endId?: string;
};
/** --- A* Algorithm --- */ /** --- A* Algorithm --- */
type AStarResult = { type AStarResult = {
@@ -153,16 +178,31 @@ function nodePathToEdges(
return edges; return edges;
} }
type VehicleDetails = {
vehicleId: string;
vehiclePosition: [number, number, number];
};
type Manager = {
pathId: string;
vehicleId: string;
};
export default function PointHandler({ export default function PointHandler({
point, point,
setPaths, // setPaths,
paths, // paths,
setHoveredPoint, setHoveredPoint,
hoveredLine, hoveredLine,
hoveredPoint, hoveredPoint,
pointIndex, pointIndex,
points, points,
setSelected,
selected,
}: PointHandlerProps) { }: PointHandlerProps) {
const { isPlaying } = usePlayButtonStore();
const [multiPaths, setMultiPaths] = useState<
{ id: number; path: PathData }[]
>([]);
const pathIdRef = useRef(1); // To ensure unique incremental IDs
const { toolMode } = useToolMode(); const { toolMode } = useToolMode();
const { activeTool } = useActiveTool(); const { activeTool } = useActiveTool();
const { scene, raycaster } = useThree(); const { scene, raycaster } = useThree();
@@ -172,29 +212,82 @@ export default function PointHandler({
const [initialPositions, setInitialPositions] = useState<{ const [initialPositions, setInitialPositions] = useState<{
paths?: any; paths?: any;
}>({}); }>({});
const [selectedPoints, setSelectedPoints] = useState<PointData[]>([]); const [shortestPaths, setShortestPaths] = useState<PathData>([]);
const [shortestEdges, setShortestEdges] = useState<PathData>([]);
const POINT_SNAP_THRESHOLD = 0.5; // Distance threshold for snapping in meters const POINT_SNAP_THRESHOLD = 0.5; // Distance threshold for snapping in meters
const [selectedPointIndices, setSelectedPointIndices] = useState<number[]>( const [vehicleUuids, setVehicleUuids] = useState<any>();
[]
);
const CAN_POINT_SNAP = true; const CAN_POINT_SNAP = true;
const CAN_ANGLE_SNAP = true; const CAN_ANGLE_SNAP = true;
const ANGLE_SNAP_DISTANCE_THRESHOLD = 0.5; const ANGLE_SNAP_DISTANCE_THRESHOLD = 0.5;
const [selectedPointIndices, setSelectedPointIndices] = useState<number[]>(
[]
);
const [shortestEdges, setShortestEdges] = useState<PathData>([]);
const { speed } = useAnimationPlaySpeed();
const { assetStore } = useSceneContext();
const { assets } = assetStore();
const vehicleMovementState = useRef<any>({});
const [activeVehicleIndex, setActiveVehicleIndex] = useState(0);
const [vehicleData, setVehicleData] = useState<VehicleDetails[]>([]);
const { paths, setPaths } = useCreatedPaths();
const [managerData, setManagerData] = useState<Manager>();
// useEffect(() => {
// const findVehicle = assets
// .filter((val) => val.eventData?.type === "Vehicle")
// ?.map((val) => val.modelUuid);
//
// setVehicleUuids(findVehicle);
// vehicleMovementState.current = {};
// findVehicle.forEach((uuid) => {
// vehicleMovementState.current[uuid] = { index: 0, progress: 0 };
// });
// }, [assets]);
useEffect(() => {
const findVehicle = assets
.filter((val) => val.eventData?.type === "Vehicle")
?.map((val) => val.modelUuid);
const findVehicleDatas = assets
.filter((val) => val.eventData?.type === "Vehicle")
?.map((val) => val);
findVehicleDatas.forEach((val) => {
const vehicledId = val.modelUuid;
const vehiclePosition: [number, number, number] = val.position;
setVehicleData((prev) => [
...prev,
{ vehicleId: vehicledId, vehiclePosition },
]);
});
setVehicleUuids(findVehicle);
setActiveVehicleIndex(0); // Reset to first vehicle
vehicleMovementState.current = {};
findVehicle.forEach((uuid) => {
vehicleMovementState.current[uuid] = {
index: 0,
progress: 0,
hasStarted: false,
};
});
}, [assets]);
const removePathByPoint = (pointId: string): PathDataInterface[] => { const removePathByPoint = (pointId: string): PathDataInterface[] => {
const removedPaths: PathDataInterface[] = []; const removedPaths: PathDataInterface[] = [];
setPaths((prevPaths) => const newPaths = paths.filter((path: PathDataInterface) => {
prevPaths.filter((path) => { const hasPoint = path.pathPoints.some(
const hasPoint = path.pathPoints.some((p) => p.pointId === pointId); (p: PointData) => p.pointId === pointId
if (hasPoint) { );
removedPaths.push(JSON.parse(JSON.stringify(path))); // keep a copy if (hasPoint) {
return false; // remove this path removedPaths.push(JSON.parse(JSON.stringify(path))); // keep a copy
} return false; // remove this path
return true; // keep this path }
}) return true; // keep this path
); });
setPaths(newPaths);
return removedPaths; return removedPaths;
}; };
@@ -288,8 +381,8 @@ export default function PointHandler({
const getAllOtherPathPoints = useCallback((): PointData[] => { const getAllOtherPathPoints = useCallback((): PointData[] => {
return ( return (
paths?.flatMap((path) => paths?.flatMap((path: PathDataInterface) =>
path.pathPoints.filter((pt) => pt.pointId !== point.pointId) path.pathPoints.filter((pt: PointData) => pt.pointId !== point.pointId)
) ?? [] ) ?? []
); );
}, [paths]); }, [paths]);
@@ -317,43 +410,7 @@ export default function PointHandler({
}, },
[getAllOtherPathPoints] [getAllOtherPathPoints]
); );
let isHandlingShiftClick = false;
// const handlePointClick = (e: any, point: PointData) => {
// if (toolMode === "3D-Delete") {
// removePathByPoint(point.pointId);
// }
// if (e.shiftKey) {
// setSelectedPointIndices((prev) => {
// if (prev.length === 0) return [pointIndex];
// if (prev.length === 1) {
// // defer shortest path calculation
// setTimeout(() => {
// console.log("points: ", points);
// const p1 = points[prev[0]];
// console.log(' p1: ', p1);
// const p2 = points[pointIndex];
// console.log('p2: ', p2);
// const result = aStarShortestPath(
// p1.pointId,
// p2.pointId,
// points,
// paths
// );
// if (result) {
// const edges = nodePathToEdges(result.pointIds, points, paths);
// console.log("edges: ", edges);
// setShortestEdges(edges);
// } else {
// setShortestEdges([]);
// }
// }, 0);
// return [prev[0], pointIndex];
// }
// return [pointIndex];
// });
// }
// };
const handlePointClick = (e: any, point: PointData) => { const handlePointClick = (e: any, point: PointData) => {
e.stopPropagation(); e.stopPropagation();
if (toolMode === "3D-Delete") { if (toolMode === "3D-Delete") {
@@ -362,53 +419,82 @@ export default function PointHandler({
} }
if (e.shiftKey) { if (e.shiftKey) {
if (isHandlingShiftClick) return; // prevent double-handling const pointIndex = points.findIndex((p) => p.pointId === point.pointId);
isHandlingShiftClick = true; if (pointIndex === -1) {
return;
setTimeout(() => { }
isHandlingShiftClick = false;
}, 100); // reset the flag after a short delay
setSelectedPointIndices((prev) => {
// console.log("Clicked point index:", pointIndex);
console.log("Previous selection:", prev);
setSelected((prev) => {
if (prev.length === 0) { if (prev.length === 0) {
console.log("first works");
return [pointIndex]; return [pointIndex];
} }
// if (prev.length === 1) {
// setTimeout(() => {
//
// const prevPoint = points[prev[0]];
//
// const newPoint = points[pointIndex];
//
// const result = aStarShortestPath(
// prevPoint.pointId,
// newPoint.pointId,
// points,
// paths
// );
// if (result) {
// const edges = nodePathToEdges(result.pointIds, points, paths);
//
// setShortestPaths(edges);
// setShortestEdges(edges);
// } else {
// setShortestPaths([]);
// setShortestEdges([]);
// }
// if (prevPoint.pointId === newPoint.pointId) {
// return prev;
// }
// }, 0);
// return [prev[0], pointIndex];
// }
// More than two points — reset
if (prev.length === 1) { if (prev.length === 1) {
if (prev[0] === pointIndex) { setTimeout(() => {
console.log("Same point selected twice — ignoring"); const prevPoint = points[prev[0]];
return prev; const newPoint = points[pointIndex];
}
const p1 = points[prev[0]]; if (prevPoint.pointId === newPoint.pointId) return;
const p2 = points[pointIndex];
console.log("Point 1:", p1);
console.log("Point 2:", p2);
if (p1 && p2) {
const result = aStarShortestPath( const result = aStarShortestPath(
p1.pointId, prevPoint.pointId,
p2.pointId, newPoint.pointId,
points, points,
paths paths
); );
if (result) { if (result) {
const edges = nodePathToEdges(result.pointIds, points, paths); const edges = nodePathToEdges(result.pointIds, points, paths);
// Create a new path object
const newPathObj = {
id: pathIdRef.current++,
path: edges,
};
setShortestPaths(edges);
setShortestEdges(edges); setShortestEdges(edges);
} else { // Append it to the list of paths
setShortestEdges([]); setMultiPaths((prevPaths) => [...prevPaths, newPathObj]);
} }
}
// Reset selection to allow new pair selection
}, 0);
return [prev[0], pointIndex]; return [prev[0], pointIndex];
} }
setShortestPaths([]);
return [pointIndex]; return [pointIndex];
}); });
} }
@@ -426,6 +512,7 @@ export default function PointHandler({
setInitialPositions({ paths: pathIntersection }); setInitialPositions({ paths: pathIntersection });
} }
}; };
const handleDrag = (point: PointData) => { const handleDrag = (point: PointData) => {
if (isHovered && dragOffset) { if (isHovered && dragOffset) {
const intersectionPoint = new Vector3(); const intersectionPoint = new Vector3();
@@ -442,7 +529,7 @@ export default function PointHandler({
// ✅ Pass newPosition and pointId // ✅ Pass newPosition and pointId
const pathSnapped = snapPathAngle(newPosition, point.pointId); const pathSnapped = snapPathAngle(newPosition, point.pointId);
const finalSnapped = snapPathPoint(pathSnapped.position); const finalSnapped = snapPathPoint(pathSnapped.position);
setPathPosition(point.pointId, finalSnapped.position, setPaths); setPathPosition(point.pointId, finalSnapped.position, setPaths, paths);
} }
} }
}; };
@@ -454,10 +541,265 @@ export default function PointHandler({
} }
}; };
useEffect(() => { const pathSegments = useMemo(() => {
console.log("selectedPoints: ", selectedPoints); if (!shortestPaths || shortestPaths.length === 0) return [];
}, [selectedPoints]);
const segments: SegmentPoint[] = [];
shortestPaths.forEach((path) => {
const [start, end] = path.pathPoints;
const startPos = new Vector3(...start.position);
const endPos = new Vector3(...end.position);
segments.push(
{ position: startPos, originalPoint: start, startId: start.pointId },
{ position: endPos, originalPoint: end, endId: end.pointId }
);
});
return segments.filter(
(v, i, arr) => i === 0 || !v.position.equals(arr[i - 1].position)
);
}, [shortestPaths]);
// useFrame((_, delta) => {
// if (!isPlaying || pathSegments.length < 2) return;
// vehicleUuids.forEach((uuid: any) => {
// const object = scene.getObjectByProperty("uuid", uuid);
// if (!object) return;
// const state = vehicleMovementState.current[uuid];
// if (!state) return;
// const startSeg = pathSegments[state.index];
// const endSeg = pathSegments[state.index + 1];
// if (!startSeg || !endSeg) return;
// const segmentDistance = startSeg.position.distanceTo(endSeg.position);
// state.progress += (speed * delta) / segmentDistance;
// while (state.progress >= 1) {
// state.progress -= 1;
// state.index++;
// if (state.index >= pathSegments.length - 1) {
// state.index = 0;
// state.progress = 0;
// object.position.copy(pathSegments[0].position);
// object.quaternion.identity(); // reset rotation
// }
// }
// const newPos = startSeg.position
// .clone()
// .lerp(endSeg.position, state.progress);
// object.position.copy(newPos);
// const forward = new Vector3(0, 0, 1);
// const targetDir = endSeg.position
// .clone()
// .sub(startSeg.position)
// .normalize();
// const targetQuat = new Quaternion().setFromUnitVectors(
// forward,
// targetDir
// );
// object.quaternion.slerp(targetQuat, 0.1);
// });
// });
function getPathIdByPoints(
startId: string | undefined,
endId: string | undefined,
shortestPaths: any[]
) {
for (const path of shortestPaths) {
for (let i = 0; i < path.pathPoints.length - 1; i++) {
const s = path.pathPoints[i];
const e = path.pathPoints[i + 1];
if (
(s.pointId === startId && e.pointId === endId) ||
(s.pointId === endId && e.pointId === startId) // handle both directions
) {
return path.pathId;
}
}
}
return null; // not found
}
//
useFrame((_, delta) => {
//
if (!isPlaying || pathSegments.length < 2 || vehicleData.length === 0)
return;
const vehicle = vehicleData[activeVehicleIndex];
if (!vehicle) return;
const uuid = vehicle.vehicleId;
const vehicleStartPos = new Vector3(...vehicle.vehiclePosition);
const object = scene.getObjectByProperty("uuid", uuid);
if (!object) return;
const state = vehicleMovementState.current[uuid];
if (!state) return;
const pathStart = pathSegments[0].position;
// Step 1: Move vehicle to the start of the path
if (!state.hasStarted) {
const distanceToStart = object.position.distanceTo(pathStart);
const step = speed * delta;
if (distanceToStart <= step) {
object.position.copy(pathStart);
object.quaternion.identity();
state.hasStarted = true; // start path animation next frame
return;
}
// Move toward path start
const direction = pathStart.clone().sub(object.position);
const distance = direction.length();
if (distance > step) {
direction.normalize();
object.position.add(direction.clone().multiplyScalar(step));
// ROTATE toward direction of movement
const forward = new Vector3(0, 0, 1); // <-- adjust this based on your model
const targetQuat = new Quaternion().setFromUnitVectors(
forward,
direction
);
object.quaternion.slerp(targetQuat, 0.1); // smooth rotation
} else {
// Snap to start segment when close enough
object.position.copy(pathStart);
object.quaternion.identity(); // reset orientation or leave as-is
vehicleMovementState.current[uuid] = { index: 0, progress: 0 };
}
return; // still approaching start
}
// Step 2: Follow the path
const startSeg = pathSegments[state.index];
const endSeg = pathSegments[state.index + 1];
if (!startSeg || !endSeg) return;
const currentPathId = getPathIdByPoints(
startSeg.startId || startSeg.endId,
endSeg.endId || endSeg.startId,
shortestPaths
);
setManagerData({ pathId: currentPathId, vehicleId: uuid });
const segmentDistance = startSeg.position.distanceTo(endSeg.position);
state.progress += (speed * delta) / segmentDistance;
while (state.progress >= 1) {
state.progress -= 1;
state.index++;
if (state.index >= pathSegments.length - 1) {
// Path complete
state.index = 0;
state.progress = 0;
state.hasStarted = false; // reset for next loop
object.position.copy(vehicleStartPos); // go back to start
object.quaternion.identity();
// Move to next vehicle
setActiveVehicleIndex((prevIndex) =>
prevIndex + 1 >= vehicleData.length ? 0 : prevIndex + 1
);
return;
}
}
const newPos = startSeg.position
.clone()
.lerp(endSeg.position, state.progress);
object.position.copy(newPos);
const forward = new Vector3(0, 0, 1);
const targetDir = endSeg.position
.clone()
.sub(startSeg.position)
.normalize();
const targetQuat = new Quaternion().setFromUnitVectors(forward, targetDir);
object.quaternion.slerp(targetQuat, 0.1);
});
// useFrame((_, delta) => {
// if (!isPlaying || pathSegments.length < 2 || vehicleData.length === 0)
// return;
// const vehicle = vehicleData[activeVehicleIndex];
// if (!vehicle) return;
// const uuid = vehicle.vehicleId;
// const vehiclePosition = vehicle.vehiclePosition;
// const object = scene.getObjectByProperty("uuid", uuid);
// if (!object) return;
// const state = vehicleMovementState.current[uuid];
// if (!state) return;
// const startSeg = pathSegments[state.index];
// const endSeg = pathSegments[state.index + 1];
// if (!startSeg || !endSeg) return;
// const segmentDistance = startSeg.position.distanceTo(endSeg.position);
// state.progress += (speed * delta) / segmentDistance;
// while (state.progress >= 1) {
// state.progress -= 1;
// state.index++;
// // If finished path
// if (state.index >= pathSegments.length - 1) {
// state.index = 0;
// state.progress = 0;
// object.position.copy(pathSegments[0].position);
// object.quaternion.identity();
// // Move to next vehicle
// setActiveVehicleIndex((prevIndex) =>
// prevIndex + 1 >= vehicleUuids.length ? 0 : prevIndex + 1
// );
// return; // Stop updating this frame
// }
// }
// const newPos = startSeg.position
// .clone()
// .lerp(endSeg.position, state.progress);
// object.position.copy(newPos);
// const forward = new Vector3(0, 0, 1);
// const targetDir = endSeg.position
// .clone()
// .sub(startSeg.position)
// .normalize();
// const targetQuat = new Quaternion().setFromUnitVectors(forward, targetDir);
// object.quaternion.slerp(targetQuat, 0.1);
// });
useEffect(() => {}, [multiPaths]);
const manager = usePathManager(managerData?.pathId, managerData?.vehicleId);
useEffect(() => {
// if (managerData) {
// console.log("manager: ", manager);
// }
}, [managerData]);
return ( return (
<> <>
<DragControls <DragControls
@@ -496,6 +838,14 @@ export default function PointHandler({
<meshBasicMaterial color="pink" /> <meshBasicMaterial color="pink" />
</mesh> </mesh>
</DragControls> </DragControls>
{shortestEdges.map((edge) => (
<Line
key={`sp-${edge.pathId}`}
points={edge.pathPoints.map((p) => p.position)}
color="yellow"
lineWidth={3}
/>
))}
</> </>
); );
} }

View File

@@ -446,7 +446,7 @@ type PointData = {
interface PathDataInterface { interface PathDataInterface {
pathId: string; pathId: string;
pathPoints: [PointData, PointData]; // always two points pathPoints: [PointData, PointData];
} }
type PathData = PathDataInterface[]; type PathData = PathDataInterface[];
@@ -602,7 +602,7 @@ export default function PointHandlers({
const handleARef = useRef<THREE.Mesh>(null); const handleARef = useRef<THREE.Mesh>(null);
const handleBRef = useRef<THREE.Mesh>(null); const handleBRef = useRef<THREE.Mesh>(null);
const lineRef = useRef<any>(null); const lineRef = useRef<any>(null);
const { gl, controls, raycaster } = useThree(); const { gl, controls, raycaster } = useThree();
const [dragging, setDragging] = useState< const [dragging, setDragging] = useState<
null | "main" | "handleA" | "handleB" null | "main" | "handleA" | "handleB"
@@ -616,11 +616,13 @@ export default function PointHandlers({
if (e.shiftKey) { if (e.shiftKey) {
setSelected((prev) => { setSelected((prev) => {
console.log("prev: ", prev);
console.log("pointIndex: ", pointIndex);
if (prev.length === 0) return [pointIndex]; if (prev.length === 0) return [pointIndex];
if (prev.length === 1) { if (prev.length === 1) {
// defer shortest path calculation // defer shortest path calculation
setTimeout(() => { setTimeout(() => {
console.log('points: ', points); console.log("points: ", points);
const p1 = points[prev[0]]; const p1 = points[prev[0]];
const p2 = points[pointIndex]; const p2 = points[pointIndex];
const result = aStarShortestPath( const result = aStarShortestPath(
@@ -631,7 +633,7 @@ export default function PointHandlers({
); );
if (result) { if (result) {
const edges = nodePathToEdges(result.pointIds, points, paths); const edges = nodePathToEdges(result.pointIds, points, paths);
console.log('edges: ', edges); console.log("edges: ", edges);
setShortestEdges(edges); setShortestEdges(edges);
setShortestPath(edges); setShortestPath(edges);
} else { } else {
@@ -767,6 +769,8 @@ export default function PointHandlers({
} }
}); });
return ( return (
<> <>
{/* Main point */} {/* Main point */}

View File

@@ -33,7 +33,7 @@ function Vehicles() {
<PathCreator /> <PathCreator />
{/* <StructuredPath /> */} {/* <StructuredPath /> */}
{/* <PreDefinedPath /> */} {/* <PreDefinedPath /> */}
{/* <VehicleInstances /> */} <VehicleInstances />
{isVehicleSelected && selectedEventSphere && !isPlaying && <VehicleUI />} {isVehicleSelected && selectedEventSphere && !isPlaying && <VehicleUI />}
</> </>
); );

View File

@@ -4,74 +4,74 @@ import { io } from "socket.io-client";
import * as CONSTANTS from "../../types/world/worldConstants"; import * as CONSTANTS from "../../types/world/worldConstants";
export const useSocketStore = create<any>((set: any, get: any) => ({ export const useSocketStore = create<any>((set: any, get: any) => ({
socket: null, socket: null,
initializeSocket: ( initializeSocket: (
email?: string, email?: string,
organization?: string, organization?: string,
token?: string, token?: string,
refreshToken?: string refreshToken?: string
) => { ) => {
const existingSocket = get().socket; const existingSocket = get().socket;
if (existingSocket) { if (existingSocket) {
return; return;
} }
const socket = io( const socket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`, `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`,
{ {
reconnection: true, reconnection: true,
auth: { token, refreshToken }, auth: { token, refreshToken },
} }
); );
const visualizationSocket = io( const visualizationSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`, `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`,
{ {
reconnection: true, reconnection: true,
auth: { token, refreshToken }, auth: { token, refreshToken },
} }
); );
const dashBoardSocket = io( const dashBoardSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`, `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
{ {
reconnection: true, reconnection: true,
auth: { token, refreshToken }, auth: { token, refreshToken },
} }
); );
const projectSocket = io( const projectSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`, `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`,
{ {
reconnection: true, reconnection: true,
auth: { token, refreshToken }, auth: { token, refreshToken },
} }
); );
const threadSocket = io( const threadSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/thread`, `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/thread`,
{ {
reconnection: true, reconnection: true,
auth: { token, refreshToken }, auth: { token, refreshToken },
} }
); );
set({ set({
socket, socket,
visualizationSocket, visualizationSocket,
dashBoardSocket, dashBoardSocket,
projectSocket, projectSocket,
threadSocket, threadSocket,
}); });
}, },
disconnectSocket: () => { disconnectSocket: () => {
set((state: any) => { set((state: any) => {
state.socket?.disconnect(); state.socket?.disconnect();
state.visualizationSocket?.disconnect(); state.visualizationSocket?.disconnect();
state.dashBoardSocket?.disconnect(); state.dashBoardSocket?.disconnect();
state.projectSocket?.disconnect(); state.projectSocket?.disconnect();
state.threadSocket?.disconnect(); state.threadSocket?.disconnect();
return { socket: null }; return { socket: null };
}); });
}, },
})); }));
// export const useSocketStore = create<any>((set: any, get: any) => ({ // export const useSocketStore = create<any>((set: any, get: any) => ({
// socket: null, // socket: null,
@@ -129,516 +129,543 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
// }, // },
// })); // }));
export const useLoadingProgress = create<{ export const useLoadingProgress = create<{
loadingProgress: number; loadingProgress: number;
setLoadingProgress: (x: number) => void; setLoadingProgress: (x: number) => void;
}>((set) => ({ }>((set) => ({
loadingProgress: 1, loadingProgress: 1,
setLoadingProgress: (x: number) => set({ loadingProgress: x }), setLoadingProgress: (x: number) => set({ loadingProgress: x }),
})); }));
export const useOrganization = create<any>((set: any) => ({ export const useOrganization = create<any>((set: any) => ({
organization: "", organization: "",
setOrganization: (x: any) => set(() => ({ organization: x })), setOrganization: (x: any) => set(() => ({ organization: x })),
})); }));
export const useToggleView = create<any>((set: any) => ({ export const useToggleView = create<any>((set: any) => ({
toggleView: false, toggleView: false,
setToggleView: (x: any) => set(() => ({ toggleView: x })), setToggleView: (x: any) => set(() => ({ toggleView: x })),
})); }));
export const useRoomsState = create<any>((set: any) => ({ export const useRoomsState = create<any>((set: any) => ({
roomsState: [], roomsState: [],
setRoomsState: (x: any) => set(() => ({ roomsState: x })), setRoomsState: (x: any) => set(() => ({ roomsState: x })),
})); }));
export const useSelectedItem = create<any>((set: any) => ({ export const useSelectedItem = create<any>((set: any) => ({
selectedItem: { selectedItem: {
name: "", name: "",
id: "", id: "",
type: undefined, type: undefined,
category: "", category: "",
subType: "", subType: "",
}, },
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })), setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
})); }));
export const useNavMesh = create<any>((set: any) => ({ export const useNavMesh = create<any>((set: any) => ({
navMesh: null, navMesh: null,
setNavMesh: (x: any) => set({ navMesh: x }), setNavMesh: (x: any) => set({ navMesh: x }),
})); }));
type SelectedAssetsState = { type SelectedAssetsState = {
selectedAssets: Object3D[]; selectedAssets: Object3D[];
setSelectedAssets: (assets: Object3D[]) => void; setSelectedAssets: (assets: Object3D[]) => void;
}; };
export const useSelectedAssets = create<SelectedAssetsState>((set) => ({ export const useSelectedAssets = create<SelectedAssetsState>((set) => ({
selectedAssets: [], selectedAssets: [],
setSelectedAssets: (assets) => set({ selectedAssets: assets }), setSelectedAssets: (assets) => set({ selectedAssets: assets }),
})); }));
export const useLayers = create<any>((set: any) => ({ export const useLayers = create<any>((set: any) => ({
Layers: 1, Layers: 1,
setLayers: (x: any) => set(() => ({ Layers: x })), setLayers: (x: any) => set(() => ({ Layers: x })),
})); }));
export const useCamPosition = create<any>((set: any) => ({ export const useCamPosition = create<any>((set: any) => ({
camPosition: { x: undefined, y: undefined, z: undefined }, camPosition: { x: undefined, y: undefined, z: undefined },
setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }), setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }),
})); }));
export const useMenuVisible = create<any>((set: any) => ({ export const useMenuVisible = create<any>((set: any) => ({
menuVisible: false, menuVisible: false,
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })), setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
})); }));
export const useToolMode = create<any>((set: any) => ({ export const useToolMode = create<any>((set: any) => ({
toolMode: null, toolMode: null,
setToolMode: (x: any) => set(() => ({ toolMode: x })), setToolMode: (x: any) => set(() => ({ toolMode: x })),
})); }));
export const useSelectedWallItem = create<any>((set: any) => ({ export const useSelectedWallItem = create<any>((set: any) => ({
selectedWallItem: null, selectedWallItem: null,
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })), setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
})); }));
export const useSelectedFloorItem = create<any>((set: any) => ({ export const useSelectedFloorItem = create<any>((set: any) => ({
selectedFloorItem: null, selectedFloorItem: null,
setSelectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })), setSelectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
})); }));
export const useDeletableFloorItem = create<any>((set: any) => ({ export const useDeletableFloorItem = create<any>((set: any) => ({
deletableFloorItem: null, deletableFloorItem: null,
setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })), setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })),
})); }));
export const useSetScale = create<any>((set: any) => ({ export const useSetScale = create<any>((set: any) => ({
scale: null, scale: null,
setScale: (x: any) => set(() => ({ scale: x })), setScale: (x: any) => set(() => ({ scale: x })),
})); }));
export const useRoofVisibility = create<any>((set: any) => ({ export const useRoofVisibility = create<any>((set: any) => ({
roofVisibility: false, roofVisibility: false,
setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })), setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
})); }));
export const useWallVisibility = create<any>((set: any) => ({ export const useWallVisibility = create<any>((set: any) => ({
wallVisibility: false, wallVisibility: false,
setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })), setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })),
})); }));
export const useShadows = create<any>((set: any) => ({ export const useShadows = create<any>((set: any) => ({
shadows: false, shadows: false,
setShadows: (x: any) => set(() => ({ shadows: x })), setShadows: (x: any) => set(() => ({ shadows: x })),
})); }));
export const useSunPosition = create<any>((set: any) => ({ export const useSunPosition = create<any>((set: any) => ({
sunPosition: { x: undefined, y: undefined, z: undefined }, sunPosition: { x: undefined, y: undefined, z: undefined },
setSunPosition: (newSuntPosition: any) => setSunPosition: (newSuntPosition: any) =>
set({ sunPosition: newSuntPosition }), set({ sunPosition: newSuntPosition }),
})); }));
export const useRemoveLayer = create<any>((set: any) => ({ export const useRemoveLayer = create<any>((set: any) => ({
removeLayer: false, removeLayer: false,
setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })), setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })),
})); }));
export const useRemovedLayer = create<any>((set: any) => ({ export const useRemovedLayer = create<any>((set: any) => ({
removedLayer: null, removedLayer: null,
setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })), setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })),
})); }));
export const useProjectName = create<any>((set: any) => ({ export const useProjectName = create<any>((set: any) => ({
projectName: "Creating Your Project", projectName: "Creating Your Project",
setProjectName: (x: any) => set({ projectName: x }), setProjectName: (x: any) => set({ projectName: x }),
})); }));
export const useActiveLayer = create<any>((set: any) => ({ export const useActiveLayer = create<any>((set: any) => ({
activeLayer: 1, activeLayer: 1,
setActiveLayer: (x: any) => set({ activeLayer: x }), setActiveLayer: (x: any) => set({ activeLayer: x }),
})); }));
export const useResetCamera = create<any>((set: any) => ({ export const useResetCamera = create<any>((set: any) => ({
resetCamera: false, resetCamera: false,
setResetCamera: (x: any) => set({ resetCamera: x }), setResetCamera: (x: any) => set({ resetCamera: x }),
})); }));
export const useAddAction = create<any>((set: any) => ({ export const useAddAction = create<any>((set: any) => ({
addAction: null, addAction: null,
setAddAction: (x: any) => set({ addAction: x }), setAddAction: (x: any) => set({ addAction: x }),
})); }));
export const useActiveTool = create<any>((set: any) => ({ export const useActiveTool = create<any>((set: any) => ({
activeTool: "cursor", activeTool: "cursor",
setActiveTool: (x: any) => set({ activeTool: x }), setActiveTool: (x: any) => set({ activeTool: x }),
})); }));
export const useActiveSubTool = create<any>((set: any) => ({ export const useActiveSubTool = create<any>((set: any) => ({
activeSubTool: "cursor", activeSubTool: "cursor",
setActiveSubTool: (x: any) => set({ activeSubTool: x }), setActiveSubTool: (x: any) => set({ activeSubTool: x }),
})); }));
export const useElevation = create<any>((set: any) => ({ export const useElevation = create<any>((set: any) => ({
elevation: 45, elevation: 45,
setElevation: (x: any) => set({ elevation: x }), setElevation: (x: any) => set({ elevation: x }),
})); }));
export const useAzimuth = create<any>((set: any) => ({ export const useAzimuth = create<any>((set: any) => ({
azimuth: -160, azimuth: -160,
setAzimuth: (x: any) => set({ azimuth: x }), setAzimuth: (x: any) => set({ azimuth: x }),
})); }));
export const useRenderDistance = create<any>((set: any) => ({ export const useRenderDistance = create<any>((set: any) => ({
renderDistance: 40, renderDistance: 40,
setRenderDistance: (x: any) => set({ renderDistance: x }), setRenderDistance: (x: any) => set({ renderDistance: x }),
})); }));
export const useCamMode = create<any>((set: any) => ({ export const useCamMode = create<any>((set: any) => ({
camMode: "ThirdPerson", camMode: "ThirdPerson",
setCamMode: (x: any) => set({ camMode: x }), setCamMode: (x: any) => set({ camMode: x }),
})); }));
export const useUserName = create<any>((set: any) => ({ export const useUserName = create<any>((set: any) => ({
userName: "", userName: "",
setUserName: (x: any) => set({ userName: x }), setUserName: (x: any) => set({ userName: x }),
})); }));
export const useRenameModeStore = create<any>((set: any) => ({ export const useRenameModeStore = create<any>((set: any) => ({
isRenameMode: false, isRenameMode: false,
setIsRenameMode: (state: boolean) => set({ isRenameMode: state }), setIsRenameMode: (state: boolean) => set({ isRenameMode: state }),
})); }));
export const useObjectPosition = create<any>((set: any) => ({ export const useObjectPosition = create<any>((set: any) => ({
objectPosition: { x: undefined, y: undefined, z: undefined }, objectPosition: { x: undefined, y: undefined, z: undefined },
setObjectPosition: (newObjectPosition: any) => setObjectPosition: (newObjectPosition: any) =>
set({ objectPosition: newObjectPosition }), set({ objectPosition: newObjectPosition }),
})); }));
export const useObjectRotation = create<any>((set: any) => ({ export const useObjectRotation = create<any>((set: any) => ({
objectRotation: { x: undefined, y: undefined, z: undefined }, objectRotation: { x: undefined, y: undefined, z: undefined },
setObjectRotation: (newObjectRotation: any) => setObjectRotation: (newObjectRotation: any) =>
set({ objectRotation: newObjectRotation }), set({ objectRotation: newObjectRotation }),
})); }));
export const useDrieTemp = create<any>((set: any) => ({ export const useDrieTemp = create<any>((set: any) => ({
drieTemp: undefined, drieTemp: undefined,
setDrieTemp: (x: any) => set({ drieTemp: x }), setDrieTemp: (x: any) => set({ drieTemp: x }),
})); }));
export const useActiveUsers = create<any>((set: any) => ({ export const useActiveUsers = create<any>((set: any) => ({
activeUsers: [], activeUsers: [],
setActiveUsers: (callback: (prev: any[]) => any[] | any[]) => setActiveUsers: (callback: (prev: any[]) => any[] | any[]) =>
set((state: { activeUsers: any[] }) => ({ set((state: { activeUsers: any[] }) => ({
activeUsers: activeUsers:
typeof callback === "function" ? callback(state.activeUsers) : callback, typeof callback === "function" ? callback(state.activeUsers) : callback,
})), })),
})); }));
export const useDrieUIValue = create<any>((set: any) => ({ export const useDrieUIValue = create<any>((set: any) => ({
drieUIValue: { touch: null, temperature: null, humidity: null }, drieUIValue: { touch: null, temperature: null, humidity: null },
setDrieUIValue: (x: any) => setDrieUIValue: (x: any) =>
set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })), set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })),
setTouch: (value: any) => setTouch: (value: any) =>
set((state: any) => ({ set((state: any) => ({
drieUIValue: { ...state.drieUIValue, touch: value }, drieUIValue: { ...state.drieUIValue, touch: value },
})), })),
setTemperature: (value: any) => setTemperature: (value: any) =>
set((state: any) => ({ set((state: any) => ({
drieUIValue: { ...state.drieUIValue, temperature: value }, drieUIValue: { ...state.drieUIValue, temperature: value },
})), })),
setHumidity: (value: any) => setHumidity: (value: any) =>
set((state: any) => ({ set((state: any) => ({
drieUIValue: { ...state.drieUIValue, humidity: value }, drieUIValue: { ...state.drieUIValue, humidity: value },
})), })),
})); }));
export const usezoneTarget = create<any>((set: any) => ({ export const usezoneTarget = create<any>((set: any) => ({
zoneTarget: [], zoneTarget: [],
setZoneTarget: (x: any) => set({ zoneTarget: x }), setZoneTarget: (x: any) => set({ zoneTarget: x }),
})); }));
export const usezonePosition = create<any>((set: any) => ({ export const usezonePosition = create<any>((set: any) => ({
zonePosition: [], zonePosition: [],
setZonePosition: (x: any) => set({ zonePosition: x }), setZonePosition: (x: any) => set({ zonePosition: x }),
})); }));
interface EditPositionState { interface EditPositionState {
Edit: boolean; Edit: boolean;
setEdit: (value: boolean) => void; setEdit: (value: boolean) => void;
} }
export const useEditPosition = create<EditPositionState>((set) => ({ export const useEditPosition = create<EditPositionState>((set) => ({
Edit: false, Edit: false,
setEdit: (value) => set({ Edit: value }), setEdit: (value) => set({ Edit: value }),
})); }));
export const useAsset3dWidget = create<any>((set: any) => ({ export const useAsset3dWidget = create<any>((set: any) => ({
widgetSelect: "", widgetSelect: "",
setWidgetSelect: (x: any) => set({ widgetSelect: x }), setWidgetSelect: (x: any) => set({ widgetSelect: x }),
})); }));
export const useWidgetSubOption = create<any>((set: any) => ({ export const useWidgetSubOption = create<any>((set: any) => ({
widgetSubOption: "2D", widgetSubOption: "2D",
setWidgetSubOption: (x: any) => set({ widgetSubOption: x }), setWidgetSubOption: (x: any) => set({ widgetSubOption: x }),
})); }));
export const useLimitDistance = create<any>((set: any) => ({ export const useLimitDistance = create<any>((set: any) => ({
limitDistance: true, limitDistance: true,
setLimitDistance: (x: any) => set({ limitDistance: x }), setLimitDistance: (x: any) => set({ limitDistance: x }),
})); }));
export const useTileDistance = create<any>((set: any) => ({ export const useTileDistance = create<any>((set: any) => ({
gridValue: { gridValue: {
size: CONSTANTS.gridConfig.size, size: CONSTANTS.gridConfig.size,
divisions: CONSTANTS.gridConfig.divisions, divisions: CONSTANTS.gridConfig.divisions,
}, },
planeValue: { planeValue: {
height: CONSTANTS.planeConfig.height, height: CONSTANTS.planeConfig.height,
width: CONSTANTS.planeConfig.width, width: CONSTANTS.planeConfig.width,
}, },
setGridValue: (value: any) => setGridValue: (value: any) =>
set((state: any) => ({ set((state: any) => ({
gridValue: { ...state.gridValue, ...value }, gridValue: { ...state.gridValue, ...value },
})), })),
setPlaneValue: (value: any) => setPlaneValue: (value: any) =>
set((state: any) => ({ set((state: any) => ({
planeValue: { ...state.planeValue, ...value }, planeValue: { ...state.planeValue, ...value },
})), })),
})); }));
export const usePlayAgv = create<any>((set, get) => ({ export const usePlayAgv = create<any>((set, get) => ({
PlayAgv: [], PlayAgv: [],
setPlayAgv: (updateFn: (prev: any[]) => any[]) => setPlayAgv: (updateFn: (prev: any[]) => any[]) =>
set({ PlayAgv: updateFn(get().PlayAgv) }), set({ PlayAgv: updateFn(get().PlayAgv) }),
})); }));
// Define the Asset type // Define the Asset type
type Asset = { type Asset = {
id: string; id: string;
name: string; name: string;
position?: [number, number, number]; // Optional: 3D position position?: [number, number, number]; // Optional: 3D position
rotation?: { x: number; y: number; z: number }; // Optional: Euler rotation rotation?: { x: number; y: number; z: number }; // Optional: Euler rotation
}; };
// Zustand store type // Zustand store type
type ZoneAssetState = { type ZoneAssetState = {
zoneAssetId: Asset | null; zoneAssetId: Asset | null;
setZoneAssetId: (asset: Asset | null) => void; setZoneAssetId: (asset: Asset | null) => void;
}; };
// Zustand store // Zustand store
export const useZoneAssetId = create<ZoneAssetState>((set) => ({ export const useZoneAssetId = create<ZoneAssetState>((set) => ({
zoneAssetId: null, zoneAssetId: null,
setZoneAssetId: (asset) => set({ zoneAssetId: asset }), setZoneAssetId: (asset) => set({ zoneAssetId: asset }),
})); }));
// version visible hidden // version visible hidden
interface VersionHistoryState { interface VersionHistoryState {
viewVersionHistory: boolean; viewVersionHistory: boolean;
setVersionHistoryVisible: (value: boolean) => void; setVersionHistoryVisible: (value: boolean) => void;
} }
const useVersionHistoryVisibleStore = create<VersionHistoryState>((set) => ({ const useVersionHistoryVisibleStore = create<VersionHistoryState>((set) => ({
viewVersionHistory: false, viewVersionHistory: false,
setVersionHistoryVisible: (value) => set({ viewVersionHistory: value }), setVersionHistoryVisible: (value) => set({ viewVersionHistory: value }),
})); }));
export default useVersionHistoryVisibleStore; export default useVersionHistoryVisibleStore;
interface ShortcutStore { interface ShortcutStore {
showShortcuts: boolean; showShortcuts: boolean;
setShowShortcuts: (value: boolean) => void; setShowShortcuts: (value: boolean) => void;
toggleShortcuts: () => void; toggleShortcuts: () => void;
} }
export const useShortcutStore = create<ShortcutStore>((set) => ({ export const useShortcutStore = create<ShortcutStore>((set) => ({
showShortcuts: false, showShortcuts: false,
setShowShortcuts: (value) => set({ showShortcuts: value }), setShowShortcuts: (value) => set({ showShortcuts: value }),
toggleShortcuts: () => toggleShortcuts: () =>
set((state) => ({ showShortcuts: !state.showShortcuts })), set((state) => ({ showShortcuts: !state.showShortcuts })),
})); }));
export const useMachineCount = create<any>((set: any) => ({ export const useMachineCount = create<any>((set: any) => ({
machineCount: 0, machineCount: 0,
setMachineCount: (x: any) => set({ machineCount: x }), setMachineCount: (x: any) => set({ machineCount: x }),
})); }));
export const useMachineUptime = create<any>((set: any) => ({ export const useMachineUptime = create<any>((set: any) => ({
machineActiveTime: 0, machineActiveTime: 0,
setMachineActiveTime: (x: any) => set({ machineActiveTime: x }), setMachineActiveTime: (x: any) => set({ machineActiveTime: x }),
})); }));
export const useMachineDowntime = create<any>((set: any) => ({ export const useMachineDowntime = create<any>((set: any) => ({
machineIdleTime: 0, machineIdleTime: 0,
setMachineIdleTime: (x: any) => set({ machineIdleTime: x }), setMachineIdleTime: (x: any) => set({ machineIdleTime: x }),
})); }));
export const useMaterialCycle = create<any>((set: any) => ({ export const useMaterialCycle = create<any>((set: any) => ({
materialCycleTime: 0, materialCycleTime: 0,
setMaterialCycleTime: (x: any) => set({ materialCycleTime: x }), setMaterialCycleTime: (x: any) => set({ materialCycleTime: x }),
})); }));
export const useThroughPutData = create<any>((set: any) => ({ export const useThroughPutData = create<any>((set: any) => ({
throughputData: 0, throughputData: 0,
setThroughputData: (x: any) => set({ throughputData: x }), setThroughputData: (x: any) => set({ throughputData: x }),
})); }));
export const useProductionCapacityData = create<any>((set: any) => ({ export const useProductionCapacityData = create<any>((set: any) => ({
productionCapacityData: 0, productionCapacityData: 0,
setProductionCapacityData: (x: any) => set({ productionCapacityData: x }), setProductionCapacityData: (x: any) => set({ productionCapacityData: x }),
})); }));
export const useProcessBar = create<any>((set: any) => ({ export const useProcessBar = create<any>((set: any) => ({
processBar: [], processBar: [],
setProcessBar: (x: any) => set({ processBar: x }), setProcessBar: (x: any) => set({ processBar: x }),
})); }));
export const useDfxUpload = create<any>((set: any) => ({ export const useDfxUpload = create<any>((set: any) => ({
dfxuploaded: [], dfxuploaded: [],
dfxWallGenerate: [], dfxWallGenerate: [],
objValue: { x: 0, y: 0, z: 0 }, objValue: { x: 0, y: 0, z: 0 },
setDfxUploaded: (x: any) => set({ dfxuploaded: x }), setDfxUploaded: (x: any) => set({ dfxuploaded: x }),
setDxfWallGenerate: (x: any) => set({ dfxWallGenerate: x }), setDxfWallGenerate: (x: any) => set({ dfxWallGenerate: x }),
setObjValue: (x: any) => set({ objValue: x }), setObjValue: (x: any) => set({ objValue: x }),
})); }));
type InputValuesStore = { type InputValuesStore = {
inputValues: Record<string, string>; inputValues: Record<string, string>;
setInputValues: (values: Record<string, string>) => void; setInputValues: (values: Record<string, string>) => void;
updateInputValue: (label: string, value: string) => void; // <- New updateInputValue: (label: string, value: string) => void; // <- New
}; };
export const useInputValues = create<InputValuesStore>((set) => ({ export const useInputValues = create<InputValuesStore>((set) => ({
inputValues: {}, inputValues: {},
setInputValues: (values) => set({ inputValues: values }), setInputValues: (values) => set({ inputValues: values }),
updateInputValue: (label, value) => updateInputValue: (label, value) =>
set((state) => ({ set((state) => ({
inputValues: { inputValues: {
...state.inputValues, ...state.inputValues,
[label]: value, [label]: value,
}, },
})), })),
})); }));
export interface ROISummaryData { export interface ROISummaryData {
productName: string; productName: string;
roiPercentage: number; roiPercentage: number;
paybackPeriod: number; paybackPeriod: number;
totalCost: number; totalCost: number;
revenueGenerated: number; revenueGenerated: number;
netProfit: number; netProfit: number;
netLoss: number; netLoss: number;
} }
interface ROISummaryStore { interface ROISummaryStore {
roiSummary: ROISummaryData; roiSummary: ROISummaryData;
setRoiSummaryData: (values: ROISummaryData) => void; setRoiSummaryData: (values: ROISummaryData) => void;
} }
export const useROISummaryData = create<ROISummaryStore>((set) => ({ export const useROISummaryData = create<ROISummaryStore>((set) => ({
roiSummary: { roiSummary: {
productName: "", productName: "",
roiPercentage: 0, roiPercentage: 0,
paybackPeriod: 0, paybackPeriod: 0,
totalCost: 0, totalCost: 0,
revenueGenerated: 0, revenueGenerated: 0,
netProfit: 0, netProfit: 0,
netLoss: 0, netLoss: 0,
}, },
setRoiSummaryData: (values) => set({ roiSummary: values }), setRoiSummaryData: (values) => set({ roiSummary: values }),
})); }));
interface CompareStore { interface CompareStore {
comparePopUp: boolean; comparePopUp: boolean;
setComparePopUp: (value: boolean) => void; setComparePopUp: (value: boolean) => void;
toggleComparePopUp: () => void; toggleComparePopUp: () => void;
} }
export const useCompareStore = create<CompareStore>((set) => ({ export const useCompareStore = create<CompareStore>((set) => ({
comparePopUp: false, comparePopUp: false,
setComparePopUp: (value) => set({ comparePopUp: value }), setComparePopUp: (value) => set({ comparePopUp: value }),
toggleComparePopUp: () => toggleComparePopUp: () =>
set((state) => ({ comparePopUp: !state.comparePopUp })), set((state) => ({ comparePopUp: !state.comparePopUp })),
})); }));
// Save state store // Save state store
interface SaveVersionStore { interface SaveVersionStore {
isVersionSaved: boolean; isVersionSaved: boolean;
setIsVersionSaved: (value: boolean) => void; setIsVersionSaved: (value: boolean) => void;
} }
export const useSaveVersion = create<SaveVersionStore>((set) => ({ export const useSaveVersion = create<SaveVersionStore>((set) => ({
isVersionSaved: false, isVersionSaved: false,
setIsVersionSaved: (value: boolean) => set({ isVersionSaved: value }), setIsVersionSaved: (value: boolean) => set({ isVersionSaved: value }),
})); }));
interface ViewSceneState { interface ViewSceneState {
viewSceneLabels: boolean; viewSceneLabels: boolean;
setViewSceneLabels: (value: boolean | ((prev: boolean) => boolean)) => void; setViewSceneLabels: (value: boolean | ((prev: boolean) => boolean)) => void;
} }
export const useViewSceneStore = create<ViewSceneState>((set) => ({ export const useViewSceneStore = create<ViewSceneState>((set) => ({
viewSceneLabels: getInitialViewSceneLabels(), viewSceneLabels: getInitialViewSceneLabels(),
setViewSceneLabels: (value) => { setViewSceneLabels: (value) => {
set((state) => { set((state) => {
const newValue = const newValue =
typeof value === "function" ? value(state.viewSceneLabels) : value; typeof value === "function" ? value(state.viewSceneLabels) : value;
// Store in localStorage manually // Store in localStorage manually
localStorage.setItem("viewSceneLabels", JSON.stringify(newValue)); localStorage.setItem("viewSceneLabels", JSON.stringify(newValue));
return { viewSceneLabels: newValue }; return { viewSceneLabels: newValue };
}); });
}, },
})); }));
function getInitialViewSceneLabels(): boolean { function getInitialViewSceneLabels(): boolean {
if (typeof window === "undefined") return false; // SSR safety if (typeof window === "undefined") return false; // SSR safety
const saved = localStorage.getItem("viewSceneLabels"); const saved = localStorage.getItem("viewSceneLabels");
return saved ? JSON.parse(saved) : false; return saved ? JSON.parse(saved) : false;
} }
export interface CompareProduct { export interface CompareProduct {
productUuid: string; productUuid: string;
productName: string; productName: string;
simulationData: { simulationData: {
// costPerUnit: number; // costPerUnit: number;
// workingDaysPerYear: number; // workingDaysPerYear: number;
// shiftLength: number; // shiftLength: number;
// shiftsPerDay: number; // shiftsPerDay: number;
roiPercentage: number; roiPercentage: number;
// paybackPeriod: number; // paybackPeriod: number;
// totalCost: number; // totalCost: number;
// revenueGenerated: number; // revenueGenerated: number;
netProfit: number; netProfit: number;
productionCapacity: number; productionCapacity: number;
paybackPeriod: number; paybackPeriod: number;
// netLoss: number; // netLoss: number;
machineIdleTime: number; machineIdleTime: number;
machineActiveTime: number; machineActiveTime: number;
throughputData: number; throughputData: number;
}; };
} }
export const useCompareProductDataStore = create<{ export const useCompareProductDataStore = create<{
compareProductsData: CompareProduct[]; compareProductsData: CompareProduct[];
setCompareProductsData: (x: CompareProduct[]) => void; setCompareProductsData: (x: CompareProduct[]) => void;
}>((set) => ({ }>((set) => ({
compareProductsData: [], compareProductsData: [],
setCompareProductsData: (x) => set({ compareProductsData: x }), setCompareProductsData: (x) => set({ compareProductsData: x }),
})); }));
export const useSelectedComment = create<any>((set: any) => ({ export const useSelectedComment = create<any>((set: any) => ({
selectedComment: null, selectedComment: null,
setSelectedComment: (x: any) => set({ selectedComment: x }), setSelectedComment: (x: any) => set({ selectedComment: x }),
position2Dstate: {}, position2Dstate: {},
setPosition2Dstate: (x: any) => set({ position2Dstate: x }), setPosition2Dstate: (x: any) => set({ position2Dstate: x }),
commentPositionState: null, commentPositionState: null,
setCommentPositionState: (x: any) => set({ commentPositionState: x }), setCommentPositionState: (x: any) => set({ commentPositionState: x }),
})); }));
export const useSelectedPath = create<any>((set: any) => ({ export const useSelectedPath = create<any>((set: any) => ({
selectedPath: "auto", selectedPath: "auto",
setSelectedPath: (x: any) => set({ selectedPath: x }), setSelectedPath: (x: any) => set({ selectedPath: x }),
})); }));
export const useContextActionStore = create<any>((set: any) => ({ export const useContextActionStore = create<any>((set: any) => ({
contextAction: null, contextAction: null,
setContextAction: (x: any) => set({ contextAction: x }), setContextAction: (x: any) => set({ contextAction: x }),
}));
type PointData = {
pointId: string;
position: [number, number, number];
isCurved?: boolean;
handleA?: [number, number, number] | null;
handleB?: [number, number, number] | null;
};
interface PathDataInterface {
pathId: string;
isActive?: boolean;
isCurved?: boolean;
pathPoints: [PointData, PointData];
}
interface allPaths {
paths: string;
isAvailable: boolean;
vehicleId: string;
}
type PathData = PathDataInterface[];
export const useCreatedPaths = create<any>((set: any) => ({
paths: [],
setPaths: (x: PathData) => set({ paths: x }),
allPaths: [],
setAllPaths: (x: allPaths) => set({ allPaths: x }),
})); }));