diff --git a/app/src/components/temporary/SelectFloorPlan.tsx b/app/src/components/temporary/SelectFloorPlan.tsx index 310b2b0..8c47785 100644 --- a/app/src/components/temporary/SelectFloorPlan.tsx +++ b/app/src/components/temporary/SelectFloorPlan.tsx @@ -1,10 +1,12 @@ import React, { useEffect, useState } from "react"; import useLayoutStore from "../../store/builder/uselayoutStore"; -import { useDfxUpload } from "../../store/builder/store"; +import { useActiveLayer, useDfxUpload } from "../../store/builder/store"; import DxfParser from "dxf-parser"; import { getWallPointsFromBlueprint } from "../../modules/builder/dfx/functions/getWallPointsFromBlueprint"; import { convertDXFToThree } from "../../modules/builder/dfx/functions/convertDxfToThree"; import { AIIcon } from "../icons/ExportCommonIcons"; +import { useBuilderStore } from "../../store/builder/useBuilderStore"; +import { useSceneContext } from "../../modules/scene/sceneContext"; type DXFData = any; const SelectFloorPlan: React.FC = () => { // Access layout state and state setters @@ -12,10 +14,13 @@ const SelectFloorPlan: React.FC = () => { // Access DXF-related states and setters const { setDfxUploaded, setDfxGenerate, setObjValue, objValue } = useDfxUpload(); - + const { activeLayer } = useActiveLayer(); + const { wallThickness, wallHeight, insideMaterial, outsideMaterial } = useBuilderStore(); + const { wallStore } = useSceneContext(); + const { addWall } = wallStore(); // Local state to store the parsed DXF file const [parsedFile, setParsedFile] = useState(undefined); - + const { walls } = wallStore(); // Flag to trigger generation after file upload const [generate, setGenerate] = useState(false); @@ -60,6 +65,7 @@ const SelectFloorPlan: React.FC = () => { parsedData: parsedFile, setDfxGenerate, objValue, + wallThickness, wallHeight, outsideMaterial, insideMaterial, activeLayer, addWall, walls }); } }, [generate]); diff --git a/app/src/modules/builder/dfx/LoadBlueprint.tsx b/app/src/modules/builder/dfx/LoadBlueprint.tsx index 1a95268..0a1f3e4 100644 --- a/app/src/modules/builder/dfx/LoadBlueprint.tsx +++ b/app/src/modules/builder/dfx/LoadBlueprint.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef } from 'react'; -import { useDfxUpload, useSocketStore, useToggleView, useUpdateScene } from '../../../store/builder/store'; +import { useActiveLayer, useDfxUpload, useSocketStore, useToggleView, useUpdateScene } from '../../../store/builder/store'; import { LineBasicMaterial, Line } from 'three'; import { TransformControls } from '@react-three/drei'; import { getWallPointsFromBlueprint } from './functions/getWallPointsFromBlueprint'; @@ -7,6 +7,8 @@ import * as Types from '../../../types/world/worldTypes'; import { useParams } from 'react-router-dom'; import { getUserData } from '../../../functions/getUserData'; import { useVersionContext } from '../version/versionContext'; +import { useBuilderStore } from '../../../store/builder/useBuilderStore'; +import { useSceneContext } from '../../scene/sceneContext'; /** * DxfFile component handles the rendering and manipulation of DXf file data in a 3D scene. @@ -22,41 +24,37 @@ const DxfFile = () => { const { selectedVersion } = selectedVersionStore(); const { projectId } = useParams(); const { userId, organization } = getUserData(); - + const { activeLayer } = useActiveLayer(); + const { wallThickness, wallHeight, insideMaterial, outsideMaterial, } = useBuilderStore(); // Refs for storing line objects const lineRefs = useRef([]); - + const { wallStore } = useSceneContext(); + const { addWall, } = wallStore(); + const { walls } = wallStore(); + /** * Effect hook that runs when DXF wall generation is triggered. * Loads initial points and lines from the DXF data and updates the scene. */ useEffect(() => { + if (dfxWallGenerate) { - // Store generated lines in ref - // lines.current.push(...dfxWallGenerate); - // dfxWallGenerate.map((line: any) => { - // const lineData = arrayLineToObject(line as Types.Line); + dfxWallGenerate.map((wall: Wall) => { + const data = { + wallData: wall, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + addWall(wall); + socket.emit('v1:model-Wall:add', data); + // API - // //REST - - // // setLine(organization, lineData.layer!, lineData.line!, lineData.type!); - - // //SOCKET - - // const input = { - // organization, - // layer: lineData.layer, - // line: lineData.line, - // type: lineData.type, - // socketId: socket.id, - // versionId: selectedVersion?.versionId || '', - // projectId, - // userId - // } - - // socket.emit('v1:Line:create', input); - - // }) + // if (projectId) { + // upsertWallApi(projectId, selectedVersion?.versionId || '', wall); + // } + }) } }, [dfxWallGenerate]); @@ -79,6 +77,7 @@ const DxfFile = () => { getWallPointsFromBlueprint({ objValue: { x: position.x, y: position.y, z: position.z }, setDfxGenerate: () => { }, + wallThickness, wallHeight, outsideMaterial, insideMaterial, activeLayer, addWall, walls }); }; diff --git a/app/src/modules/builder/dfx/functions/getWallPointsFromBlueprint.ts b/app/src/modules/builder/dfx/functions/getWallPointsFromBlueprint.ts index a1a5e45..1050a8c 100644 --- a/app/src/modules/builder/dfx/functions/getWallPointsFromBlueprint.ts +++ b/app/src/modules/builder/dfx/functions/getWallPointsFromBlueprint.ts @@ -1,11 +1,21 @@ import { MathUtils, Vector3, BufferGeometry } from "three"; +import { useActiveLayer } from "../../../../store/builder/store"; +import { useBuilderStore } from "../../../../store/builder/useBuilderStore"; +import { wait } from "@testing-library/user-event/dist/utils"; type DXFData = any; // Replace with actual DXF data type type DXFEntity = any; // Replace with actual DXF entity type type WallLineVertex = [Vector3, string, number, string]; // Represents a wall segment with start point, ID, weight, and type interface Props { parsedData?: DXFData; // Parsed DXF file data - setDfxGenerate?: (walls: WallLineVertex[][]) => void; // Callback to set generated walls + setDfxGenerate?: any; // Callback to set generated walls objValue: any; // Object position values for offset calculation + wallThickness: number; + wallHeight: number; + outsideMaterial: string; + insideMaterial: string; + activeLayer: number; // Active layer for wall points + addWall: (wall: Wall) => void; // Function to add a wall to the scene + walls: Wall[]; // Array of walls to be processed } /** @@ -22,14 +32,20 @@ export function getWallPointsFromBlueprint({ parsedData, setDfxGenerate, objValue, + wallThickness, + wallHeight, + outsideMaterial, + insideMaterial, + activeLayer, + addWall, + walls, }: Props) { // Early return if no data is provided if (!parsedData) return; if (!parsedData.entities) return; const unit = 1000; // Conversion factor from millimeters to meters - const wallVertex: WallLineVertex[][] = []; // Stores all generated wall segments - + const wallVertex: any[] = []; // Array to store wall vertices // Process each entity in the DXF file parsedData.entities.forEach((entity: DXFEntity) => { // Handle LINE entities @@ -47,31 +63,39 @@ export function getWallPointsFromBlueprint({ -entity.vertices[1].y / unit ).add(new Vector3(objValue.x, 0, objValue.z)); - // Check if points already exist to avoid duplicates - const existingStart = wallVertex - .flat() - .find((v) => v[0].equals(startVec)); - const startPoint: WallLineVertex = existingStart || [ - startVec, - MathUtils.generateUUID(), // Generate unique ID for new points - 1, // Default weight - "WallLine", // Type identifier - ]; + // Create start and end points + const startPoint: Point = { + pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points + pointType: "Wall", // Type identifier + position: [startVec.x, startVec.y, startVec.z], // Position in 3D space + layer: activeLayer, // Default weight + }; - const existingEnd = wallVertex.flat().find((v) => v[0].equals(endVec)); - const endPoint: WallLineVertex = existingEnd || [ - endVec, - MathUtils.generateUUID(), - 1, - "WallLine", - ]; + const endPoint: Point = { + pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points + pointType: "Wall", // Type identifier + position: [endVec.x, endVec.y, endVec.z], // Position in 3D space + layer: activeLayer, + }; - // Add the line segment to our collection - wallVertex.push([startPoint, endPoint]); + // Create the wall + const wallSet: Wall = { + wallUuid: MathUtils.generateUUID(), + points: [startPoint, endPoint], // Store start and end points + outsideMaterial: insideMaterial, + insideMaterial: outsideMaterial, + wallThickness: wallThickness, + wallHeight: wallHeight, + decals: [], + }; + wallVertex.push(wallSet); // Store wall segment in array + // Add the wall to the scene + // addWall(wallSet); } + // Handle LWPOLYLINE entities (connected line segments) else if (entity.type === "LWPOLYLINE" && entity.vertices) { - let firstPoint: WallLineVertex | undefined; // Store first point for closing the polyline + let firstPoint: Point | undefined; // Store first point for closing the polyline // Process each vertex pair in the polyline for (let i = 0; i < entity.vertices.length - 1; i++) { @@ -88,37 +112,58 @@ export function getWallPointsFromBlueprint({ -entity.vertices[i + 1].y / unit ).add(new Vector3(objValue.x, 0, objValue.z)); - // Check for existing points - const existingStart = wallVertex - .flat() - .find((v) => v[0].equals(startVec)); - const startPoint: WallLineVertex = existingStart || [ - startVec, - MathUtils.generateUUID(), - 1, - "WallLine", - ]; + // Create start and end points + const startPoint: Point = { + pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points + pointType: "Wall", // Type identifier + position: [startVec.x, startVec.y, startVec.z], // Position in 3D space + layer: activeLayer, + }; - const existingEnd = wallVertex.flat().find((v) => v[0].equals(endVec)); - const endPoint: WallLineVertex = existingEnd || [ - endVec, - MathUtils.generateUUID(), - 1, - "WallLine", - ]; + const endPoint: Point = { + pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points + pointType: "Wall", // Type identifier + position: [endVec.x, endVec.y, endVec.z], // Position in 3D space + layer: activeLayer, + }; - wallVertex.push([startPoint, endPoint]); + // Create the wall segment + const wallSet: Wall = { + wallUuid: MathUtils.generateUUID(), + points: [startPoint, endPoint], // Store start and end points + outsideMaterial: insideMaterial, + insideMaterial: outsideMaterial, + wallThickness: wallThickness, + wallHeight: wallHeight, + decals: [], + }; + // Add the wall segment + // addWall(wallSet); + wallVertex.push(wallSet); // Store first point and create closing segment if this is the last vertex if (i === 0) firstPoint = startPoint; if (i === entity.vertices.length - 2 && firstPoint) { - wallVertex.push([endPoint, firstPoint]); + const closingWallSet: Wall = { + wallUuid: MathUtils.generateUUID(), + points: [endPoint, firstPoint], // Create closing segment + outsideMaterial: insideMaterial, + insideMaterial: outsideMaterial, + wallThickness: wallThickness, + wallHeight: wallHeight, + decals: [], + }; + // Add the closing wall + wallVertex.push(closingWallSet); + // addWall(closingWallSet); } } } + // Handle ARC entities else if (entity.type === "ARC") { const { center, radius, startAngle, endAngle } = entity; + // Validate required ARC properties if ( !center || @@ -154,28 +199,38 @@ export function getWallPointsFromBlueprint({ const startVec = arcPoints[i]; const endVec = arcPoints[i + 1]; - // Check for existing points - const existingStart = wallVertex - .flat() - .find((v) => v[0].equals(startVec)); - const startPoint: WallLineVertex = existingStart || [ - startVec, - MathUtils.generateUUID(), - 1, - "WallLine", - ]; + // Create start and end points + const startPoint: Point = { + pointUuid: MathUtils.generateUUID(), + pointType: "Wall", + position: [startVec.x, startVec.y, startVec.z], + layer: activeLayer, + }; - const existingEnd = wallVertex.flat().find((v) => v[0].equals(endVec)); - const endPoint: WallLineVertex = existingEnd || [ - endVec, - MathUtils.generateUUID(), - 1, - "WallLine", - ]; + const endPoint: Point = { + pointUuid: MathUtils.generateUUID(), + pointType: "Wall", + position: [endVec.x, endVec.y, endVec.z], + layer: activeLayer, + }; - wallVertex.push([startPoint, endPoint]); + // Create the wall segment + const wallSet: Wall = { + wallUuid: MathUtils.generateUUID(), + points: [startPoint, endPoint], + outsideMaterial: insideMaterial, + insideMaterial: outsideMaterial, + wallThickness: wallThickness, + wallHeight: wallHeight, + decals: [], + }; + + // Add the wall segment + // addWall(wallSet); + wallVertex.push(wallSet); } } + // Log unsupported entity types else { console.error("Unsupported entity type:", entity.type); diff --git a/app/src/modules/builder/wall/wallCreator/wallCreator.tsx b/app/src/modules/builder/wall/wallCreator/wallCreator.tsx index a80a62d..24a2f95 100644 --- a/app/src/modules/builder/wall/wallCreator/wallCreator.tsx +++ b/app/src/modules/builder/wall/wallCreator/wallCreator.tsx @@ -71,6 +71,7 @@ function WallCreator() { if (wallIntersect && !pointIntersects) { const wall = getWallByPoints(wallIntersect.object.userData.points); + console.log('wall: ', wall); if (wall) { const ThroughPoint = wallIntersect.object.userData.path.getPoints(Constants.lineConfig.lineIntersectionPoints); let intersectionPoint = getClosestIntersection(ThroughPoint, wallIntersect.point); @@ -294,7 +295,9 @@ function WallCreator() { position: [position.x, position.y, position.z], layer: activeLayer }; + console.log('newPoint: ', newPoint); + console.log('snappedPoint: ', snappedPoint); if (snappedPosition && snappedPoint) { newPoint.pointUuid = snappedPoint.pointUuid; newPoint.position = snappedPosition; @@ -316,6 +319,7 @@ function WallCreator() { } } + console.log('tempPoints: ', tempPoints); if (tempPoints.length === 0) { setTempPoints([newPoint]); setIsCreating(true); @@ -330,6 +334,7 @@ function WallCreator() { decals: [] }; addWall(wall); + console.log('wall: ', wall); // API diff --git a/app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx b/app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx index 34d9f26..f22cef4 100644 --- a/app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx +++ b/app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx @@ -12,13 +12,12 @@ interface PolygonGeneratorProps { export default function PolygonGenerator({ groupRef, }: PolygonGeneratorProps) { - const { aisleStore } = useSceneContext(); + const { aisleStore, wallStore } = useSceneContext(); const { aisles } = aisleStore(); const { scene } = useThree(); + const { walls } = wallStore(); useEffect(() => { - // let allLines = arrayLinesToObject(lines.current); - // const wallLines = allLines?.filter((line) => line?.type === "WallLine"); const result = aisles .filter( (aisle) => @@ -61,9 +60,12 @@ export default function PolygonGenerator({ }); }); - // const wallPoints = wallLines - // .map((pair) => pair?.line.map((vals) => vals.position)) - // .filter((wall): wall is THREE.Vector3[] => !!wall); + + const wallPoints: THREE.Vector3[][] = walls + .map((wall) => + wall.points.map((pt) => new THREE.Vector3(pt.position[0], pt.position[1], pt.position[2])) + ) + .filter(points => points.length === 2); if (!result || result.some((line) => !line)) { @@ -81,7 +83,7 @@ export default function PolygonGenerator({ const polygons = turf.polygonize(turf.featureCollection(validLineFeatures)); - // renderWallGeometry(wallPoints); + renderWallGeometry(wallPoints); if (polygons.features.length > 0) { polygons.features.forEach((feature) => { @@ -116,7 +118,7 @@ export default function PolygonGenerator({ }); } - }, [ aisles, scene]); + }, [aisles, scene, walls]); const renderWallGeometry = (walls: THREE.Vector3[][]) => { walls.forEach((wall) => { diff --git a/app/src/utils/shortcutkeys/handleShortcutKeys.ts b/app/src/utils/shortcutkeys/handleShortcutKeys.ts index 7090eaa..1f84558 100644 --- a/app/src/utils/shortcutkeys/handleShortcutKeys.ts +++ b/app/src/utils/shortcutkeys/handleShortcutKeys.ts @@ -1,10 +1,14 @@ import React, { useEffect } from "react"; -import useModuleStore, { useSubModuleStore, useThreeDStore } from "../../store/useModuleStore"; +import useModuleStore, { + useSubModuleStore, + useThreeDStore, +} from "../../store/useModuleStore"; import { usePlayerStore, useToggleStore } from "../../store/useUIToggleStore"; import useVersionHistoryVisibleStore, { useActiveSubTool, useActiveTool, useAddAction, + useDfxUpload, useRenameModeStore, useSaveVersion, useSelectedComment, @@ -49,7 +53,7 @@ const KeyPressListener: React.FC = () => { const { setCreateNewVersion } = useVersionHistoryStore(); const { setVersionHistoryVisible } = useVersionHistoryVisibleStore(); const { setSelectedComment } = useSelectedComment(); - + const { setDfxUploaded, setDfxGenerate } = useDfxUpload(); const isTextInput = (element: Element | null): boolean => element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || @@ -160,14 +164,14 @@ const KeyPressListener: React.FC = () => { setCreateNewVersion(true); setVersionHistoryVisible(true); setSubModule("properties"); - setActiveModule('builder'); + setActiveModule("builder"); break; case "Ctrl+H": if (!isPlaying) { setVersionHistoryVisible(true); setSubModule("properties"); - setActiveModule('builder'); + setActiveModule("builder"); } break; @@ -195,6 +199,7 @@ const KeyPressListener: React.FC = () => { clearComparisonProduct(); setIsLogListVisible(false); setIsRenameMode(false); + setDfxUploaded([]); setSelectedComment(null); }