Files
Dwinzo_Demo/app/src/modules/builder/wall/Instances/wallInstances.tsx
Jerald-Golden-B 23e7ba39e8 Refactor builder module and remove unused components
- Removed CalculateAreaGroup and computeArea function as they were no longer needed.
- Updated Floor2DInstance and Zone2DInstance to calculate area and centroid using new utility functions.
- Refactored WallInstances to include Floor2D rendering and improved area display.
- Cleaned up imports and ensured consistent formatting across files.
- Enhanced performance by memoizing calculations for area and centroid.
- Removed deprecated state management for rooms and version history visibility.
2025-09-08 13:46:47 +05:30

204 lines
8.2 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 { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { useSceneContext } from "../../../scene/sceneContext";
import { useToggleView, useToolMode } 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";
import useModuleStore from "../../../../store/ui/useModuleStore";
import getCenteroidPoint from "../../functions/getCenteroid";
import getArea from "../../functions/getArea";
function WallInstances() {
const { wallStore } = useSceneContext();
const { setSelectedWall, selectedWall } = useBuilderStore();
const { toolMode } = useToolMode();
const { toggleView } = useToggleView();
const { activeModule } = useModuleStore();
const { walls } = wallStore();
const { rooms } = useWallClassification(walls);
useEffect(() => {
// console.log('walls: ', walls);
}, [walls]);
useEffect(() => {
if (!toggleView && activeModule === "builder") {
if (toolMode !== "cursor") {
if (selectedWall) setSelectedWall(null);
}
} else {
if (selectedWall) setSelectedWall(null);
}
}, [toggleView, toolMode, activeModule, selectedWall]);
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.map((wall) => (
<WallInstance key={wall.wallUuid} wall={wall} />
))}
<group name="Wall-Floors-Group">
{rooms.map((room, index) => (
<Floor3D key={index} room={room} />
))}
</group>
</>
)}
{toggleView && (
<>
<group name="Wall-Points-Group">
{allPoints.map((point) => (
<Point key={point.pointUuid} point={point} />
))}
</group>
<group name="Wall-Floors-Group">
{rooms.map((room, index) => (
<Floor2D key={index} room={room} />
))}
</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 Floor3D({ room }: { readonly 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 castShadow 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>
);
}
function Floor2D({ room }: { readonly room: Point[] }) {
const savedTheme: string | null = localStorage.getItem("theme");
const points2D = useMemo(() => {
return room.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
}, [room]);
const shape = useMemo(() => {
const shape = new Shape();
shape.moveTo(points2D[0].x, points2D[0].y);
for (let i = 1; i < points2D.length; i++) {
shape.lineTo(points2D[i].x, points2D[i].y);
}
shape.lineTo(points2D[0].x, points2D[0].y);
return shape;
}, [points2D]);
const area = useMemo(() => getArea(points2D), [points2D]);
const centroid: [number, number, number] = useMemo(() => {
const center = getCenteroidPoint(points2D);
if (!center) return [0, Constants.floorConfig.height + 0.01, 0];
return [center.x, Constants.floorConfig.height + 0.01, center.y] as [number, number, number];
}, [points2D]);
if (!shape) return null;
const formattedArea = `${area.toFixed(2)}`;
return (
<>
<mesh castShadow receiveShadow name="Wall-Floor" rotation={[Math.PI / 2, 0, 0]}>
<Extrude receiveShadow castShadow name="Wall-Floor" args={[shape, { depth: Constants.floorConfig.height }]} position={[0, 0, 0]}>
<meshBasicMaterial color={savedTheme === "dark" ? Constants.lineConfig.wallColor : Constants.lineConfig.wallColor} side={DoubleSide} transparent opacity={0.4} depthWrite={false} />
</Extrude>
</mesh>
<Html position={centroid} wrapperClass="distance-text-wrapper" className="distance-text" zIndexRange={[1, 0]} prepend center sprite>
<div className="distance area">({formattedArea})</div>
</Html>
</>
);
}