Add dragging and rotating state management to simulation store; enhance PointsCreator and VehicleUI components
This commit is contained in:
parent
928c683a79
commit
96530b981f
|
@ -1,22 +1,29 @@
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
|
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
|
||||||
import useModuleStore from "../../../../../store/useModuleStore";
|
import useModuleStore, { useSubModuleStore } from "../../../../../store/useModuleStore";
|
||||||
import { TransformControls } from "@react-three/drei";
|
import { TransformControls } from "@react-three/drei";
|
||||||
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
|
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
|
||||||
import {
|
import {
|
||||||
useSelectedEventSphere,
|
useSelectedEventSphere,
|
||||||
useSelectedEventData,
|
useSelectedEventData,
|
||||||
|
useIsDragging,
|
||||||
|
useIsRotating,
|
||||||
} from "../../../../../store/simulation/useSimulationStore";
|
} from "../../../../../store/simulation/useSimulationStore";
|
||||||
|
import { useThree } from "@react-three/fiber";
|
||||||
|
|
||||||
function PointsCreator() {
|
function PointsCreator() {
|
||||||
|
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||||
|
const { subModule } = useSubModuleStore();
|
||||||
const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore();
|
const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const transformRef = useRef<any>(null);
|
const transformRef = useRef<any>(null);
|
||||||
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
||||||
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||||
const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere, } = useSelectedEventSphere();
|
const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere, } = useSelectedEventSphere();
|
||||||
const { selectedEventData, setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
|
const { setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
|
||||||
|
const { isDragging } = useIsDragging();
|
||||||
|
const { isRotating } = useIsRotating();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedEventSphere) {
|
if (selectedEventSphere) {
|
||||||
|
@ -72,6 +79,53 @@ function PointsCreator() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const canvasElement = gl.domElement;
|
||||||
|
|
||||||
|
let drag = false;
|
||||||
|
let isMouseDown = false;
|
||||||
|
|
||||||
|
const onMouseDown = () => {
|
||||||
|
isMouseDown = true;
|
||||||
|
drag = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMouseUp = () => {
|
||||||
|
if (selectedEventSphere && !drag) {
|
||||||
|
raycaster.setFromCamera(pointer, camera);
|
||||||
|
const intersects = raycaster
|
||||||
|
.intersectObjects(scene.children, true)
|
||||||
|
.filter(
|
||||||
|
(intersect) =>
|
||||||
|
intersect.object.name === ('Event-Sphere')
|
||||||
|
);
|
||||||
|
if (intersects.length === 0) {
|
||||||
|
clearSelectedEventSphere();
|
||||||
|
setTransformMode(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onMouseMove = () => {
|
||||||
|
if (isMouseDown) {
|
||||||
|
drag = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (subModule === 'mechanics') {
|
||||||
|
canvasElement.addEventListener("mousedown", onMouseDown);
|
||||||
|
canvasElement.addEventListener("mouseup", onMouseUp);
|
||||||
|
canvasElement.addEventListener("mousemove", onMouseMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
canvasElement.removeEventListener("mousedown", onMouseDown);
|
||||||
|
canvasElement.removeEventListener("mouseup", onMouseUp);
|
||||||
|
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||||
|
};
|
||||||
|
|
||||||
|
}, [gl, subModule, selectedEventSphere]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{activeModule === "simulation" && (
|
{activeModule === "simulation" && (
|
||||||
|
@ -92,10 +146,6 @@ function PointsCreator() {
|
||||||
sphereRefs.current[point.uuid]
|
sphereRefs.current[point.uuid]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onPointerMissed={() => {
|
|
||||||
// clearSelectedEventSphere();
|
|
||||||
setTransformMode(null);
|
|
||||||
}}
|
|
||||||
key={`${i}-${j}`}
|
key={`${i}-${j}`}
|
||||||
position={new THREE.Vector3(...point.position)}
|
position={new THREE.Vector3(...point.position)}
|
||||||
// rotation={new THREE.Euler(...point.rotation)}
|
// rotation={new THREE.Euler(...point.rotation)}
|
||||||
|
@ -120,10 +170,6 @@ function PointsCreator() {
|
||||||
sphereRefs.current[event.point.uuid]
|
sphereRefs.current[event.point.uuid]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onPointerMissed={() => {
|
|
||||||
// clearSelectedEventSphere();
|
|
||||||
setTransformMode(null);
|
|
||||||
}}
|
|
||||||
position={new THREE.Vector3(...event.point.position)}
|
position={new THREE.Vector3(...event.point.position)}
|
||||||
// rotation={new THREE.Euler(...event.point.rotation)}
|
// rotation={new THREE.Euler(...event.point.rotation)}
|
||||||
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
||||||
|
@ -146,10 +192,6 @@ function PointsCreator() {
|
||||||
sphereRefs.current[event.point.uuid]
|
sphereRefs.current[event.point.uuid]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onPointerMissed={() => {
|
|
||||||
// clearSelectedEventSphere();
|
|
||||||
setTransformMode(null);
|
|
||||||
}}
|
|
||||||
position={new THREE.Vector3(...event.point.position)}
|
position={new THREE.Vector3(...event.point.position)}
|
||||||
// rotation={new THREE.Euler(...event.point.rotation)}
|
// rotation={new THREE.Euler(...event.point.rotation)}
|
||||||
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
||||||
|
@ -172,10 +214,6 @@ function PointsCreator() {
|
||||||
sphereRefs.current[event.point.uuid]
|
sphereRefs.current[event.point.uuid]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onPointerMissed={() => {
|
|
||||||
// clearSelectedEventSphere();
|
|
||||||
setTransformMode(null);
|
|
||||||
}}
|
|
||||||
position={new THREE.Vector3(...event.point.position)}
|
position={new THREE.Vector3(...event.point.position)}
|
||||||
// rotation={new THREE.Euler(...event.point.rotation)}
|
// rotation={new THREE.Euler(...event.point.rotation)}
|
||||||
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import startEnd from "../../../../assets/gltf-glb/arrow_red.glb";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useGLTF } from '@react-three/drei';
|
import { useGLTF } from '@react-three/drei';
|
||||||
import { useFrame, useThree } from '@react-three/fiber';
|
import { useFrame, useThree } from '@react-three/fiber';
|
||||||
import { useSelectedEventSphere } from '../../../../store/simulation/useSimulationStore';
|
import { useSelectedEventSphere, useIsDragging, useIsRotating } from '../../../../store/simulation/useSimulationStore';
|
||||||
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore';
|
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore';
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
const VehicleUI = () => {
|
const VehicleUI = () => {
|
||||||
|
@ -19,8 +19,8 @@ const VehicleUI = () => {
|
||||||
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 0, 0]);
|
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 0, 0]);
|
||||||
const [startRotation, setStartRotation] = useState<[number, number, number]>([0, 0, 0]);
|
const [startRotation, setStartRotation] = useState<[number, number, number]>([0, 0, 0]);
|
||||||
const [endRotation, setEndRotation] = useState<[number, number, number]>([0, 0, 0]);
|
const [endRotation, setEndRotation] = useState<[number, number, number]>([0, 0, 0]);
|
||||||
const [isDragging, setIsDragging] = useState<"start" | "end" | null>(null);
|
const { isDragging, setIsDragging } = useIsDragging();
|
||||||
const [isRotating, setIsRotating] = useState<"start" | "end" | null>(null);
|
const { isRotating, setIsRotating } = useIsRotating();
|
||||||
const { raycaster } = useThree();
|
const { raycaster } = useThree();
|
||||||
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0));
|
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0));
|
||||||
const state: Types.ThreeState = useThree();
|
const state: Types.ThreeState = useThree();
|
||||||
|
@ -46,13 +46,13 @@ const VehicleUI = () => {
|
||||||
pickUpPoint.rotation.y,
|
pickUpPoint.rotation.y,
|
||||||
pickUpPoint.rotation.z
|
pickUpPoint.rotation.z
|
||||||
);
|
);
|
||||||
pickupPosition.y = 0;
|
pickupPosition.y = 0;
|
||||||
setStartPosition([pickupPosition.x, 0, pickupPosition.z]);
|
setStartPosition([pickupPosition.x, 0, pickupPosition.z]);
|
||||||
setStartRotation([pickupRotation.x, pickupRotation.y, pickupRotation.z]);
|
setStartRotation([pickupRotation.x, pickupRotation.y, pickupRotation.z]);
|
||||||
} else {
|
} else {
|
||||||
const defaultLocal = new THREE.Vector3(0, 0, 1.5);
|
const defaultLocal = new THREE.Vector3(0, 0, 1.5);
|
||||||
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
|
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
|
||||||
defaultWorld.y = 0;
|
defaultWorld.y = 0;
|
||||||
setStartPosition([defaultWorld.x, 0, defaultWorld.z]);
|
setStartPosition([defaultWorld.x, 0, defaultWorld.z]);
|
||||||
setStartRotation([0, 0, 0]);
|
setStartRotation([0, 0, 0]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,4 +114,36 @@ export const useSelectedAction = create<SelectedActionState>()(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
interface IsDraggingState {
|
||||||
|
isDragging: "start" | "end" | null;
|
||||||
|
setIsDragging: (state: "start" | "end" | null) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useIsDragging = create<IsDraggingState>()(
|
||||||
|
immer((set) => ({
|
||||||
|
isDragging: null,
|
||||||
|
setIsDragging: (state) => {
|
||||||
|
set((s) => {
|
||||||
|
s.isDragging = state;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
interface IsRotatingState {
|
||||||
|
isRotating: "start" | "end" | null;
|
||||||
|
setIsRotating: (state: "start" | "end" | null) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useIsRotating = create<IsRotatingState>()(
|
||||||
|
immer((set) => ({
|
||||||
|
isRotating: null,
|
||||||
|
setIsRotating: (state) => {
|
||||||
|
set((s) => {
|
||||||
|
s.isRotating = state;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}))
|
||||||
);
|
);
|
Loading…
Reference in New Issue