Enhance builder functionality by implementing drag-and-drop for lines and points, adding hover effects, and improving wall distance display in the UI.
This commit is contained in:
@@ -15,9 +15,10 @@ import { useSceneContext } from '../../scene/sceneContext';
|
||||
|
||||
function Point({ point }: { readonly point: Point }) {
|
||||
const materialRef = useRef<THREE.ShaderMaterial>(null);
|
||||
const { raycaster, camera, pointer } = useThree();
|
||||
const { raycaster, camera, pointer, gl } = useThree();
|
||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
|
||||
const { toolMode } = useToolMode();
|
||||
const { aisleStore } = useSceneContext();
|
||||
const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore();
|
||||
@@ -91,33 +92,45 @@ function Point({ point }: { readonly point: Point }) {
|
||||
}), [colors.defaultInnerColor, colors.defaultOuterColor]);
|
||||
|
||||
const handleDrag = (point: Point) => {
|
||||
if (toolMode === 'move' && isHovered) {
|
||||
if (toolMode === 'move' && isHovered && dragOffset) {
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
const intersectionPoint = new THREE.Vector3();
|
||||
const position = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||
if (point.pointType === 'Aisle') {
|
||||
if (position) {
|
||||
const newPosition: [number, number, number] = [position.x, position.y, position.z];
|
||||
const aisleSnappedPosition = snapAisleAngle(newPosition);
|
||||
const finalSnappedPosition = snapAislePoint(aisleSnappedPosition.position);
|
||||
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||
|
||||
setAislePosition(point.pointUuid, finalSnappedPosition.position);
|
||||
if (hit) {
|
||||
gl.domElement.style.cursor = 'move';
|
||||
const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
|
||||
const newPosition: [number, number, number] = [positionWithOffset.x, positionWithOffset.y, positionWithOffset.z];
|
||||
|
||||
}
|
||||
} else if (point.pointType === 'Wall') {
|
||||
if (position) {
|
||||
const newPosition: [number, number, number] = [position.x, position.y, position.z];
|
||||
const wallSnappedPosition = snapWallAngle(newPosition);
|
||||
const finalSnappedPosition = snapWallPoint(wallSnappedPosition.position);
|
||||
|
||||
setWallPosition(point.pointUuid, finalSnappedPosition.position);
|
||||
if (point.pointType === 'Aisle') {
|
||||
const aisleSnapped = snapAisleAngle(newPosition);
|
||||
const finalSnapped = snapAislePoint(aisleSnapped.position);
|
||||
setAislePosition(point.pointUuid, finalSnapped.position);
|
||||
} else if (point.pointType === 'Wall') {
|
||||
const wallSnapped = snapWallAngle(newPosition);
|
||||
const finalSnapped = snapWallPoint(wallSnapped.position);
|
||||
setWallPosition(point.pointUuid, finalSnapped.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleDragStart = (point: Point) => {
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
const intersectionPoint = new THREE.Vector3();
|
||||
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||
|
||||
if (hit) {
|
||||
const currentPosition = new THREE.Vector3(...point.position);
|
||||
const offset = new THREE.Vector3().subVectors(currentPosition, hit);
|
||||
setDragOffset(offset);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDragEnd = (point: Point) => {
|
||||
if (toolMode === '2D-Delete') return;
|
||||
gl.domElement.style.cursor = 'default';
|
||||
setDragOffset(null);
|
||||
if (toolMode !== 'move') return;
|
||||
if (point.pointType === 'Aisle') {
|
||||
const updatedAisles = getAislesByPointId(point.pointUuid);
|
||||
if (updatedAisles.length > 0 && projectId) {
|
||||
@@ -148,6 +161,7 @@ function Point({ point }: { readonly point: Point }) {
|
||||
setHoveredPoint(null);
|
||||
}
|
||||
}
|
||||
gl.domElement.style.cursor = 'default';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,8 +179,9 @@ function Point({ point }: { readonly point: Point }) {
|
||||
<DragControls
|
||||
axisLock='y'
|
||||
autoTransform={false}
|
||||
onDrag={() => { handleDrag(point) }}
|
||||
onDragEnd={() => { handleDragEnd(point) }}
|
||||
onDragStart={() => handleDragStart(point)}
|
||||
onDrag={() => handleDrag(point)}
|
||||
onDragEnd={() => handleDragEnd(point)}
|
||||
>
|
||||
<mesh
|
||||
key={point.pointUuid}
|
||||
@@ -179,12 +194,16 @@ function Point({ point }: { readonly point: Point }) {
|
||||
onPointerOver={() => {
|
||||
if (!hoveredPoint) {
|
||||
setHoveredPoint(point);
|
||||
setIsHovered(true)
|
||||
setIsHovered(true);
|
||||
if (toolMode === 'move') {
|
||||
gl.domElement.style.cursor = 'pointer';
|
||||
}
|
||||
}
|
||||
}}
|
||||
onPointerOut={() => {
|
||||
if (hoveredPoint) {
|
||||
setHoveredPoint(null);
|
||||
gl.domElement.style.cursor = 'default';
|
||||
}
|
||||
setIsHovered(false)
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user