Files
Dwinzo_Demo/app/src/modules/simulation/vehicle/pathCreator/pathHandler.tsx

188 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { DragControls, Line } from "@react-three/drei";
import React, { useMemo, useState } from "react";
import { useActiveTool, useToolMode } from "../../../../store/builder/store";
import { useThree } from "@react-three/fiber";
import { LineCurve3, Plane, Vector3 } from "three";
import { getPathsByPointId, setPathPosition } from "./function/getPaths";
import { handleCanvasCursors } from "../../../../utils/mouseUtils/handleCanvasCursors";
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];
}
type PathData = PathDataInterface[];
type PathHandlerProps = {
selectedPath: PathDataInterface;
points: [PointData, PointData];
paths: PathData;
setPaths: React.Dispatch<React.SetStateAction<PathData>>;
setHoveredLine: React.Dispatch<
React.SetStateAction<PathDataInterface | null>
>;
hoveredLine: PathDataInterface | null;
hoveredPoint: PointData | null;
};
export default function PathHandler({
selectedPath,
setPaths,
points,
paths,
setHoveredLine,
hoveredLine,
hoveredPoint,
}: PathHandlerProps) {
const { toolMode } = useToolMode();
const { scene, raycaster } = useThree();
const [dragOffset, setDragOffset] = useState<Vector3 | null>(null);
const [initialPositions, setInitialPositions] = useState<{
paths?: any;
}>({});
const [isHovered, setIsHovered] = useState(false);
const { activeTool } = useActiveTool();
const plane = useMemo(() => new Plane(new Vector3(0, 1, 0), 0), []);
const path = useMemo(() => {
const [start, end] = points.map((p) => new Vector3(...p.position));
return new LineCurve3(start, end);
}, [points]);
const removePath = (pathId: string) => {
setPaths((prevPaths) => prevPaths.filter((p) => p.pathId !== pathId));
};
const handlePathClick = (pointId: string) => {
if (toolMode === "3D-Delete") {
removePath(pointId);
}
};
const handleDragStart = (points: [PointData, PointData]) => {
if (activeTool !== "cursor") return;
const intersectionPoint = new Vector3();
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
const start = new Vector3(...points[0].position);
const end = new Vector3(...points[1].position);
const midPoint = new Vector3().addVectors(start, end).multiplyScalar(0.5);
const offset = new Vector3().subVectors(midPoint, hit);
setDragOffset(offset);
const pathSet = getPathsByPointId(points[0].pointId, paths);
setInitialPositions({ paths: pathSet });
}
};
// const handleDrag = (points: [PointData, PointData]) => {
// if (isHovered && dragOffset) {
// const intersectionPoint = new Vector3();
// const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
// if (hit) {
// handleCanvasCursors("grabbing");
// const positionWithOffset = new Vector3().addVectors(hit, dragOffset);
// const start = new Vector3(...points[0].position);
// const end = new Vector3(...points[1].position);
// const midPoint = new Vector3()
// .addVectors(start, end)
// .multiplyScalar(0.5);
// const delta = new Vector3().subVectors(positionWithOffset, midPoint);
// const newStart = new Vector3().addVectors(start, delta);
// const newEnd = new Vector3().addVectors(end, delta);
// setPathPosition(
// points[0].pointId,
// [newStart.x, newStart.y, newStart.z],
// setPaths
// );
// setPathPosition(
// points[1].pointId,
// [newEnd.x, newEnd.y, newEnd.z],
// setPaths
// );
// }
// }
// };
const handleDrag = (points: [PointData, PointData]) => {
if (isHovered && dragOffset) {
const intersectionPoint = new Vector3();
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
handleCanvasCursors("grabbing");
const positionWithOffset = new Vector3().addVectors(hit, dragOffset);
const start = new Vector3(...points[0].position);
const end = new Vector3(...points[1].position);
const midPoint = new Vector3()
.addVectors(start, end)
.multiplyScalar(0.5);
const delta = new Vector3().subVectors(positionWithOffset, midPoint);
const newStart: [number, number, number] = [
start.x + delta.x,
start.y + delta.y,
start.z + delta.z,
];
const newEnd: [number, number, number] = [
end.x + delta.x,
end.y + delta.y,
end.z + delta.z,
];
// ✅ Move both points separately (wont overwrite other updates)
setPathPosition(points[0].pointId, newStart, setPaths);
setPathPosition(points[1].pointId, newEnd, setPaths);
}
}
};
const handleDragEnd = (points: [PointData, PointData]) => {};
return (
<>
<DragControls
axisLock="y"
autoTransform={false}
onDragStart={() => handleDragStart(points)}
onDrag={() => handleDrag(points)}
onDragEnd={() => handleDragEnd(points)}
>
<Line
name="Path-Line"
key={selectedPath.pathId}
points={[points[0].position, points[1].position]}
color="purple"
lineWidth={5}
userData={selectedPath}
onClick={(e) => {
e.stopPropagation();
handlePathClick(selectedPath.pathId);
}}
onPointerOver={(e) => {
if (e.buttons === 0 && !e.ctrlKey) {
setHoveredLine(selectedPath);
setIsHovered(true);
if (!hoveredPoint) {
// handleCanvasCursors("grab");
}
}
}}
onPointerOut={() => {
if (isHovered && hoveredLine) {
setHoveredLine(null);
if (!hoveredPoint) {
// handleCanvasCursors("default");
}
}
setIsHovered(false);
}}
/>
</DragControls>
</>
);
}