added available paths
This commit is contained in:
@@ -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) => {
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ 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,
|
||||||
@@ -42,6 +42,7 @@ export const setPathPosition = (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
})
|
});
|
||||||
);
|
|
||||||
|
setPaths(newPaths);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
};
|
||||||
@@ -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}
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -135,13 +139,14 @@ export default function PathHandler({
|
|||||||
];
|
];
|
||||||
|
|
||||||
// ✅ Move both points separately (won’t overwrite other updates)
|
// ✅ Move both points separately (won’t 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
|
||||||
|
|||||||
@@ -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) {
|
if (hasPoint) {
|
||||||
removedPaths.push(JSON.parse(JSON.stringify(path))); // keep a copy
|
removedPaths.push(JSON.parse(JSON.stringify(path))); // keep a copy
|
||||||
return false; // remove this path
|
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}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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[];
|
||||||
@@ -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 */}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ function Vehicles() {
|
|||||||
<PathCreator />
|
<PathCreator />
|
||||||
{/* <StructuredPath /> */}
|
{/* <StructuredPath /> */}
|
||||||
{/* <PreDefinedPath /> */}
|
{/* <PreDefinedPath /> */}
|
||||||
{/* <VehicleInstances /> */}
|
<VehicleInstances />
|
||||||
{isVehicleSelected && selectedEventSphere && !isPlaying && <VehicleUI />}
|
{isVehicleSelected && selectedEventSphere && !isPlaying && <VehicleUI />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -642,3 +642,30 @@ 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 }),
|
||||||
|
}));
|
||||||
|
|||||||
Reference in New Issue
Block a user