144 lines
5.6 KiB
TypeScript
144 lines
5.6 KiB
TypeScript
import React, { useEffect, useMemo } from 'react';
|
|
import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from 'three';
|
|
import { Html, Extrude } from '@react-three/drei';
|
|
import { useLoader } from '@react-three/fiber';
|
|
import { useSceneContext } from '../../../scene/sceneContext';
|
|
import { useToggleView } from '../../../../store/builder/store';
|
|
import { useWallClassification } from './instance/helpers/useWallClassification';
|
|
import Line from '../../line/line';
|
|
import Point from '../../point/point';
|
|
import WallInstance from './instance/wallInstance';
|
|
import * as Constants from '../../../../types/world/worldConstants';
|
|
|
|
import texturePath from "../../../../assets/textures/floor/white.png";
|
|
import texturePathDark from "../../../../assets/textures/floor/black.png";
|
|
|
|
function WallInstances() {
|
|
const { wallStore } = useSceneContext();
|
|
const { walls } = wallStore();
|
|
const { rooms } = useWallClassification(walls);
|
|
const { toggleView } = useToggleView();
|
|
|
|
useEffect(() => {
|
|
// console.log('walls: ', walls);
|
|
}, [walls])
|
|
|
|
const allPoints = useMemo(() => {
|
|
const points: Point[] = [];
|
|
const seenUuids = new Set<string>();
|
|
|
|
walls.forEach(wall => {
|
|
wall.points.forEach(point => {
|
|
if (!seenUuids.has(point.pointUuid)) {
|
|
seenUuids.add(point.pointUuid);
|
|
points.push(point);
|
|
}
|
|
});
|
|
});
|
|
|
|
return points;
|
|
}, [walls]);
|
|
|
|
return (
|
|
<>
|
|
{!toggleView && walls.length > 1 && (
|
|
<>
|
|
{walls.map((wall) => (
|
|
<WallInstance key={wall.wallUuid} wall={wall} />
|
|
))}
|
|
|
|
<group name='Wall-Floors-Group'>
|
|
{rooms.map((room, index) => (
|
|
<Floor key={index} room={room} />
|
|
))}
|
|
</group>
|
|
</>
|
|
)}
|
|
|
|
{toggleView && (
|
|
<>
|
|
<group name='Wall-Points-Group'>
|
|
{allPoints.map((point) => (
|
|
<Point key={point.pointUuid} point={point} />
|
|
))}
|
|
</group>
|
|
|
|
<group name='Wall-Lines-Group'>
|
|
|
|
{walls.map((wall) => (
|
|
<React.Fragment key={wall.wallUuid}>
|
|
<Line points={wall.points} />
|
|
</React.Fragment>
|
|
))}
|
|
|
|
{walls.map((wall) => {
|
|
const textPosition = new Vector3().addVectors(new Vector3(...wall.points[0].position), new Vector3(...wall.points[1].position)).divideScalar(2);
|
|
const distance = new Vector3(...wall.points[0].position).distanceTo(new Vector3(...wall.points[1].position));
|
|
|
|
return (
|
|
< React.Fragment key={wall.wallUuid}>
|
|
{toggleView &&
|
|
<Html
|
|
key={`${wall.points[0].pointUuid}_${wall.points[1].pointUuid}`}
|
|
userData={wall}
|
|
position={[textPosition.x, 1, textPosition.z]}
|
|
wrapperClass="distance-text-wrapper"
|
|
className="distance-text"
|
|
zIndexRange={[1, 0]}
|
|
prepend
|
|
sprite
|
|
>
|
|
<div
|
|
key={wall.wallUuid}
|
|
className={`distance ${wall.wallUuid}`}
|
|
>
|
|
{distance.toFixed(2)} m
|
|
</div>
|
|
</Html>
|
|
}
|
|
</React.Fragment>
|
|
)
|
|
})}
|
|
|
|
</group>
|
|
</>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default WallInstances;
|
|
|
|
function Floor({ room }: { room: Point[] }) {
|
|
const savedTheme: string | null = localStorage.getItem('theme');
|
|
const textureScale = Constants.floorConfig.textureScale;
|
|
const floorTexture = useLoader(TextureLoader, savedTheme === "dark" ? texturePathDark : texturePath);
|
|
floorTexture.wrapS = floorTexture.wrapT = RepeatWrapping;
|
|
floorTexture.repeat.set(textureScale, textureScale);
|
|
floorTexture.colorSpace = SRGBColorSpace;
|
|
|
|
const shape = useMemo(() => {
|
|
const shape = new Shape();
|
|
const points = room.map(p => new 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;
|
|
}, [room]);
|
|
|
|
if (!shape) return null;
|
|
|
|
return (
|
|
<mesh name="Wall-Floor" rotation={[Math.PI / 2, 0, 0]}>
|
|
<Extrude
|
|
receiveShadow
|
|
name="Wall-Floor"
|
|
args={[shape, { depth: Constants.floorConfig.height, bevelEnabled: false }]}
|
|
position={[0, 0, 0]}
|
|
>
|
|
<meshStandardMaterial color={Constants.floorConfig.defaultColor} map={floorTexture} side={DoubleSide} />
|
|
</Extrude>
|
|
</mesh>
|
|
);
|
|
}
|