Refactor: Update useEffect dependencies to include activeLayer for ReferenceAisle, ReferenceFloor, ReferenceWall; enhance usePointSnapping with zone snapping functionality and add ReferenceZone component for zone management
This commit is contained in:
163
app/src/modules/builder/zone/zoneCreator/referenceZone.tsx
Normal file
163
app/src/modules/builder/zone/zoneCreator/referenceZone.tsx
Normal file
@@ -0,0 +1,163 @@
|
||||
import { useEffect, useRef, useState, useMemo } from 'react';
|
||||
import * as THREE from 'three';
|
||||
import { useFrame, useThree } from '@react-three/fiber';
|
||||
import { Extrude, 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 ReferenceLine from '../../line/reference/referenceLine';
|
||||
|
||||
interface ReferenceZoneProps {
|
||||
tempPoints: Point[];
|
||||
}
|
||||
|
||||
function ReferenceZone({ tempPoints }: Readonly<ReferenceZoneProps>) {
|
||||
const { zoneColor, zoneHeight, 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 [tempZone, setTempZone] = useState<Zone | null>(null);
|
||||
const [currentPosition, setCurrentPosition] = useState<[number, number, number]>(tempPoints[0]?.position);
|
||||
|
||||
const directionalSnap = useDirectionalSnapping(currentPosition, tempPoints[tempPoints.length - 1]?.position || null);
|
||||
const { snapZonePoint } = usePointSnapping({ uuid: 'temp-Zone', pointType: 'Zone', position: directionalSnap.position || [0, 0, 0], });
|
||||
|
||||
useFrame(() => {
|
||||
if (toolMode === 'Zone' && toggleView && tempPoints.length > 0) {
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
const intersectionPoint = new THREE.Vector3();
|
||||
raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||
|
||||
setCurrentPosition([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z]);
|
||||
|
||||
if (!intersectionPoint) return;
|
||||
const snapped = snapZonePoint([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z], tempPoints.slice(0, -2));
|
||||
|
||||
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 zonePoints: Point[] = [
|
||||
...tempPoints,
|
||||
{
|
||||
pointUuid: 'temp-point',
|
||||
pointType: 'Zone',
|
||||
position: finalPosition.current,
|
||||
layer: activeLayer,
|
||||
},
|
||||
];
|
||||
|
||||
setTempZone({
|
||||
zoneUuid: 'temp-zone',
|
||||
zoneName: 'temp-zone',
|
||||
points: zonePoints,
|
||||
zoneColor,
|
||||
zoneHeight,
|
||||
viewPortPosition: [0, 0, 0],
|
||||
viewPortTarget: [0, 0, 0],
|
||||
});
|
||||
|
||||
} else if (tempZone !== null) {
|
||||
setTempZone(null);
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setTempZone(null);
|
||||
}, [toolMode, toggleView, tempPoints.length, zoneColor, zoneHeight, activeLayer]);
|
||||
|
||||
const allLines = useMemo(() => {
|
||||
if (!tempZone || tempZone.points.length < 2) return [];
|
||||
|
||||
const lines: [Point, Point][] = [];
|
||||
const pts = tempZone.points;
|
||||
|
||||
for (let i = 0; i < pts.length - 1; i++) {
|
||||
lines.push([pts[i], pts[i + 1]]);
|
||||
}
|
||||
|
||||
return lines;
|
||||
}, [tempZone]);
|
||||
|
||||
if (!tempZone) return null;
|
||||
|
||||
return (
|
||||
<group name="Wall-Reference-Group">
|
||||
{allLines.map(([p1, p2], idx) => {
|
||||
const v1 = new THREE.Vector3(...p1.position);
|
||||
const v2 = new THREE.Vector3(...p2.position);
|
||||
const mid = new THREE.Vector3().addVectors(v1, v2).multiplyScalar(0.5);
|
||||
const dist = v1.distanceTo(v2);
|
||||
|
||||
return (
|
||||
<group key={`${p1.pointUuid}-${p2.pointUuid}`}>
|
||||
<ReferenceLine points={[p1, p2]} />
|
||||
{toggleView && (
|
||||
<Html
|
||||
position={[mid.x, 1, mid.z]}
|
||||
wrapperClass="distance-text-wrapper"
|
||||
className="distance-text"
|
||||
zIndexRange={[1, 0]}
|
||||
prepend
|
||||
sprite
|
||||
>
|
||||
<div className={`distance ref-line-${idx}`}>{dist.toFixed(2)} m</div>
|
||||
</Html>
|
||||
)}
|
||||
</group>
|
||||
);
|
||||
})}
|
||||
|
||||
{tempPoints.length >= 3 && (
|
||||
<Zone zone={tempZone.points} />
|
||||
)}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
export default ReferenceZone;
|
||||
|
||||
|
||||
function Zone({ zone }: { zone: Point[] }) {
|
||||
const savedTheme: string | null = localStorage.getItem('theme');
|
||||
|
||||
const shape = useMemo(() => {
|
||||
const shape = new THREE.Shape();
|
||||
const points = zone.map(p => new THREE.Vector2(p.position[0], p.position[2]));
|
||||
if (points.length < 3) return null;
|
||||
shape.moveTo(points[0].x, points[0].y);
|
||||
points.forEach((pt) => { shape.lineTo(pt.x, pt.y); });
|
||||
return shape;
|
||||
}, [zone]);
|
||||
|
||||
if (!shape) return null;
|
||||
|
||||
return (
|
||||
<group name="Zone-Ref" rotation={[Math.PI / 2, 0, 0]}>
|
||||
<Extrude
|
||||
args={[shape, { depth: 0.001, bevelEnabled: false }]}
|
||||
position={[0, 0, 0]}
|
||||
receiveShadow
|
||||
>
|
||||
<meshStandardMaterial color={savedTheme === "dark" ? "#d2baff" : "#6f42c1"} depthWrite={false} transparent opacity={0.3} side={THREE.DoubleSide} />
|
||||
</Extrude>
|
||||
</group>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,14 @@
|
||||
import React from 'react'
|
||||
import * as THREE from 'three'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useThree } from '@react-three/fiber';
|
||||
import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
|
||||
import { useSceneContext } from '../../../scene/sceneContext';
|
||||
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useVersionContext } from '../../version/versionContext';
|
||||
import { getUserData } from '../../../../functions/getUserData';
|
||||
import ReferencePoint from '../../point/reference/referencePoint';
|
||||
import ReferenceZone from './referenceZone';
|
||||
|
||||
function ZoneCreator() {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user