128 lines
5.0 KiB
TypeScript
128 lines
5.0 KiB
TypeScript
import { useEffect, useRef, useState } from 'react';
|
|
import * as THREE from 'three';
|
|
import { useFrame, useThree } from '@react-three/fiber';
|
|
import { Html } from '@react-three/drei';
|
|
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
|
|
import { useActiveLayer, useToolMode, useToggleView } from '../../../../store/builder/store';
|
|
import { useDirectionalSnapping } from '../../point/helpers/useDirectionalSnapping';
|
|
import { usePointSnapping } from '../../point/helpers/usePointSnapping';
|
|
import * as Constants from '../../../../types/world/worldConstants';
|
|
import ReferenceLine from '../../line/reference/referenceLine';
|
|
|
|
interface ReferenceWallProps {
|
|
tempPoints: Point[];
|
|
}
|
|
|
|
function ReferenceWall({ tempPoints }: Readonly<ReferenceWallProps>) {
|
|
const { wallHeight, wallThickness, setSnappedPosition, setSnappedPoint } = useBuilderStore();
|
|
|
|
const { pointer, raycaster, camera } = useThree();
|
|
const { toolMode } = useToolMode();
|
|
const { toggleView } = useToggleView();
|
|
const { activeLayer } = useActiveLayer();
|
|
const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
|
|
const finalPosition = useRef<[number, number, number] | null>(null);
|
|
|
|
const [tempWall, setTempWall] = useState<Wall | null>(null);
|
|
const [currentPosition, setCurrentPosition] = useState<[number, number, number]>(tempPoints[0]?.position);
|
|
|
|
const directionalSnap = useDirectionalSnapping(currentPosition, tempPoints[0]?.position || null);
|
|
const { checkSnapForWall } = usePointSnapping({ uuid: 'temp-wall', pointType: 'Wall', position: directionalSnap.position || [0, 0, 0] });
|
|
|
|
useFrame(() => {
|
|
if (toolMode === 'Wall' && toggleView && tempPoints.length === 1) {
|
|
raycaster.setFromCamera(pointer, camera);
|
|
const intersectionPoint = new THREE.Vector3();
|
|
raycaster.ray.intersectPlane(plane, intersectionPoint);
|
|
|
|
setCurrentPosition([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z]);
|
|
|
|
if (intersectionPoint) {
|
|
const snapped = checkSnapForWall([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z]);
|
|
|
|
if (snapped.isSnapped && snapped.snappedPoint) {
|
|
finalPosition.current = snapped.position;
|
|
setSnappedPosition(snapped.position);
|
|
setSnappedPoint(snapped.snappedPoint);
|
|
} else if (directionalSnap.isSnapped) {
|
|
finalPosition.current = directionalSnap.position;
|
|
setSnappedPosition(directionalSnap.position);
|
|
setSnappedPoint(null);
|
|
} else {
|
|
finalPosition.current = [intersectionPoint.x, intersectionPoint.y, intersectionPoint.z];
|
|
setSnappedPosition(null);
|
|
setSnappedPoint(null);
|
|
}
|
|
|
|
if (!finalPosition.current) return;
|
|
|
|
const wallPoints: [Point, Point] = [
|
|
tempPoints[0],
|
|
{
|
|
pointUuid: 'temp-point',
|
|
pointType: 'Wall',
|
|
position: finalPosition.current,
|
|
layer: activeLayer,
|
|
}
|
|
];
|
|
|
|
setTempWall({
|
|
wallUuid: 'temp-wall',
|
|
points: wallPoints,
|
|
outSideMaterial: 'default',
|
|
inSideMaterial: 'default',
|
|
wallThickness: wallThickness,
|
|
wallHeight: wallHeight,
|
|
})
|
|
|
|
}
|
|
} else if (tempWall !== null) {
|
|
setTempWall(null);
|
|
}
|
|
});
|
|
|
|
useEffect(() => {
|
|
setTempWall(null);
|
|
}, [toolMode, toggleView, tempPoints.length, wallHeight, wallThickness]);
|
|
|
|
if (!tempWall) return null;
|
|
|
|
const renderWall = () => {
|
|
return (
|
|
<ReferenceLine points={tempWall.points} />
|
|
)
|
|
};
|
|
|
|
const textPosition = new THREE.Vector3().addVectors(new THREE.Vector3(...tempWall.points[0].position), new THREE.Vector3(...tempWall.points[1].position)).divideScalar(2);
|
|
const distance = new THREE.Vector3(...tempWall.points[0].position).distanceTo(new THREE.Vector3(...tempWall.points[1].position));
|
|
|
|
const rendertext = () => {
|
|
return (
|
|
<>
|
|
{toggleView && (
|
|
<Html
|
|
key={tempWall.wallUuid}
|
|
userData={tempWall}
|
|
position={[textPosition.x, 1, textPosition.z]}
|
|
wrapperClass="distance-text-wrapper"
|
|
className="distance-text"
|
|
zIndexRange={[1, 0]}
|
|
prepend
|
|
sprite
|
|
>
|
|
<div className={`distance ${tempWall.wallUuid}`}>{distance.toFixed(2)} m</div>
|
|
</Html>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<group name="Wall-Reference-Group">
|
|
{renderWall()}
|
|
{rendertext()}
|
|
</group>
|
|
);
|
|
}
|
|
|
|
export default ReferenceWall; |