feat: Refactor HumanUi and VehicleUI components; introduce MarkerPrimitive for improved marker handling and interaction
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
import { useGLTF } from "@react-three/drei";
|
||||
import * as THREE from "three";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useSelectedEventSphere, useIsDragging, useIsRotating, } from "../../../../store/simulation/useSimulationStore";
|
||||
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||
@@ -342,41 +343,120 @@ const VehicleUI = () => {
|
||||
</group>
|
||||
|
||||
{/* Start Marker */}
|
||||
<primitive
|
||||
<VehicleMarkerPrimitive
|
||||
name="startMarker"
|
||||
object={startScene}
|
||||
ref={startMarker}
|
||||
position={startPosition}
|
||||
rotation={startRotation}
|
||||
onPointerDown={(e: any) => {
|
||||
e.stopPropagation();
|
||||
handlePointerDown(e, "start", "start");
|
||||
}}
|
||||
outerGroupRef={outerGroup}
|
||||
color="green"
|
||||
handlePointerDown={handlePointerDown}
|
||||
setIsDragging={setIsDragging}
|
||||
setIsRotating={setIsRotating}
|
||||
/>
|
||||
|
||||
{/* End Marker */}
|
||||
<VehicleMarkerPrimitive
|
||||
name="endMarker"
|
||||
object={endScene}
|
||||
position={endPosition}
|
||||
rotation={endRotation}
|
||||
outerGroupRef={outerGroup}
|
||||
color="red"
|
||||
handlePointerDown={handlePointerDown}
|
||||
setIsDragging={setIsDragging}
|
||||
setIsRotating={setIsRotating}
|
||||
/>
|
||||
</group>
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default VehicleUI;
|
||||
|
||||
export const VehicleMarkerPrimitive = ({
|
||||
name,
|
||||
object,
|
||||
position,
|
||||
rotation,
|
||||
outerGroupRef,
|
||||
color,
|
||||
handlePointerDown,
|
||||
setIsDragging,
|
||||
setIsRotating,
|
||||
}: {
|
||||
name: string;
|
||||
object: THREE.Object3D;
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
outerGroupRef: React.RefObject<THREE.Group>;
|
||||
color: string;
|
||||
handlePointerDown: (e: any, type: "start" | "end", rotation: "start" | "end") => void;
|
||||
setIsDragging: (val: any) => void;
|
||||
setIsRotating: (val: any) => void;
|
||||
}) => {
|
||||
const { scene } = useThree();
|
||||
const markerRef = useRef<THREE.Group>(null);
|
||||
const lineRef = useRef<THREE.BufferGeometry>(null);
|
||||
const [hitPoint, setHitPoint] = useState<THREE.Vector3 | null>(null);
|
||||
|
||||
useFrame(() => {
|
||||
if (!markerRef.current || !outerGroupRef.current) return;
|
||||
|
||||
const worldPos = new THREE.Vector3();
|
||||
markerRef.current.getWorldPosition(worldPos);
|
||||
const localMarkerPos = outerGroupRef.current.worldToLocal(worldPos.clone());
|
||||
|
||||
const rayOrigin = worldPos.clone();
|
||||
const direction = new THREE.Vector3(0, -1, 0);
|
||||
const raycaster = new THREE.Raycaster(rayOrigin, direction, 0.1, 1000);
|
||||
const intersects = raycaster.intersectObjects(scene.children, true);
|
||||
|
||||
const hit = intersects.find(i => i.object.name !== name);
|
||||
if (hit) {
|
||||
const localHit = outerGroupRef.current.worldToLocal(hit.point.clone());
|
||||
setHitPoint(localHit);
|
||||
|
||||
if (lineRef.current) {
|
||||
const positions = new Float32Array([
|
||||
localMarkerPos.x, localMarkerPos.y, localMarkerPos.z,
|
||||
localHit.x, localHit.y, localHit.z
|
||||
]);
|
||||
lineRef.current.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||
lineRef.current.attributes.position.needsUpdate = true;
|
||||
}
|
||||
} else {
|
||||
setHitPoint(null);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<primitive
|
||||
name={name}
|
||||
ref={markerRef}
|
||||
object={object}
|
||||
position={position}
|
||||
rotation={rotation}
|
||||
onPointerDown={(e: any) => handlePointerDown(e, name === "startMarker" ? "start" : "end", name === "startMarker" ? "start" : "end")}
|
||||
onPointerMissed={() => {
|
||||
controls.enabled = true;
|
||||
setIsDragging(null);
|
||||
setIsRotating(null);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* End Marker */}
|
||||
<primitive
|
||||
name="endMarker"
|
||||
object={endScene}
|
||||
ref={endMarker}
|
||||
position={endPosition}
|
||||
rotation={endRotation}
|
||||
onPointerDown={(e: any) => {
|
||||
e.stopPropagation();
|
||||
handlePointerDown(e, "end", "end");
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
controls.enabled = true;
|
||||
setIsDragging(null);
|
||||
setIsRotating(null);
|
||||
}}
|
||||
/>
|
||||
</group>
|
||||
) : null;
|
||||
};
|
||||
export default VehicleUI;
|
||||
{hitPoint && (
|
||||
<>
|
||||
<mesh name={`${name}-torus`} position={hitPoint} rotation={[-Math.PI / 2, 0, 0]}>
|
||||
<torusGeometry args={[0.15, 0.02, 3, 32]} />
|
||||
<meshBasicMaterial color={color} transparent opacity={0.8} depthWrite={false} />
|
||||
</mesh>
|
||||
|
||||
<line>
|
||||
<bufferGeometry ref={lineRef} />
|
||||
<lineBasicMaterial color={color} />
|
||||
</line>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user