diff --git a/app/src/components/layout/sidebarLeft/Assets.tsx b/app/src/components/layout/sidebarLeft/Assets.tsx index c08ef78..2d4aa34 100644 --- a/app/src/components/layout/sidebarLeft/Assets.tsx +++ b/app/src/components/layout/sidebarLeft/Assets.tsx @@ -127,6 +127,7 @@ const Assets: React.FC = () => { ]; const { selectedSubCategory, setSelectedSubCategory } = useDecalStore(); + return (
@@ -208,9 +209,8 @@ const Assets: React.FC = () => { {activeSubcategories.map((cat, index) => (
setSelectedSubCategory(cat.name)} >
{cat.icon}
diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index 0041aaf..ae9c908 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -1,29 +1,13 @@ import React, { useEffect, useState } from "react"; import Header from "./Header"; -import useModuleStore, { - useSubModuleStore, -} from "../../../store/useModuleStore"; -import { - AnalysisIcon, - FilePackageIcon, - MechanicsIcon, - PropertiesIcon, - SimulationIcon, -} from "../../icons/SimulationIcons"; +import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore"; +import { AnalysisIcon, FilePackageIcon, MechanicsIcon, PropertiesIcon, SimulationIcon, } from "../../icons/SimulationIcons"; import { useToggleStore } from "../../../store/useUIToggleStore"; import Visualization from "./visualization/Visualization"; import Analysis from "./analysis/Analysis"; import Simulations from "./simulation/Simulations"; -import useVersionHistoryVisibleStore, { - useDecalStore, - useSaveVersion, - useSelectedFloorItem, - useToolMode, -} from "../../../store/builder/store"; -import { - useSelectedEventData, - useSelectedEventSphere, -} from "../../../store/simulation/useSimulationStore"; +import useVersionHistoryVisibleStore, { useDecalStore, useSaveVersion, useSelectedFloorItem, useToolMode, } from "../../../store/builder/store"; +import { useSelectedEventData, useSelectedEventSphere, } from "../../../store/simulation/useSimulationStore"; import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import GlobalProperties from "./properties/GlobalProperties"; import AssetProperties from "./properties/AssetProperties"; @@ -36,318 +20,272 @@ import FloorProperties from "./properties/FloorProperties"; import SelectedWallProperties from "./properties/SelectedWallProperties"; import SelectedFloorProperties from "./properties/SelectedFloorProperties"; import ResourceManagement from "./resourceManagement/ResourceManagement"; -import DecalProperties from "./properties/DecalProperties"; +import SelectedDecalProperties from "./properties/SelectedDecalProperties"; type DisplayComponent = - | "versionHistory" - | "globalProperties" - | "aisleProperties" - | "wallProperties" - | "floorProperties" - | "assetProperties" - | "selectedWallProperties" - | "selectedFloorProperties" - | "zoneProperties" - | "simulations" - | "mechanics" - | "analysis" - | "visualization" - | "selectedDecalProperties" - | "resourceManagement" - | "none"; + | "versionHistory" + | "globalProperties" + | "aisleProperties" + | "wallProperties" + | "floorProperties" + | "assetProperties" + | "selectedWallProperties" + | "selectedFloorProperties" + | "zoneProperties" + | "simulations" + | "mechanics" + | "analysis" + | "visualization" + | "selectedDecalProperties" + | "resourceManagement" + | "none"; const SideBarRight: React.FC = () => { - const { activeModule } = useModuleStore(); - const { toggleUIRight } = useToggleStore(); - const { toolMode } = useToolMode(); - const { subModule, setSubModule } = useSubModuleStore(); - const { selectedFloorItem } = useSelectedFloorItem(); - const { selectedWall, selectedFloor, selectedAisle } = useBuilderStore(); - const { selectedEventData } = useSelectedEventData(); - const { selectedEventSphere } = useSelectedEventSphere(); - const { viewVersionHistory, setVersionHistoryVisible } = - useVersionHistoryVisibleStore(); - const { isVersionSaved } = useSaveVersion(); - const { selectedSubCategory } = useDecalStore(); + const { selectedDecal } = useBuilderStore(); + const { activeModule } = useModuleStore(); + const { toggleUIRight } = useToggleStore(); + const { toolMode } = useToolMode(); + const { subModule, setSubModule } = useSubModuleStore(); + const { selectedFloorItem } = useSelectedFloorItem(); + const { selectedWall, selectedFloor, selectedAisle } = useBuilderStore(); + const { selectedEventData } = useSelectedEventData(); + const { selectedEventSphere } = useSelectedEventSphere(); + const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore(); + const { isVersionSaved } = useSaveVersion(); - const [displayComponent, setDisplayComponent] = - useState("none"); + const [displayComponent, setDisplayComponent] = useState("none"); - useEffect(() => { - if (activeModule !== "simulation") setSubModule("properties"); - if (activeModule === "simulation") setSubModule("simulations"); - }, [activeModule, setSubModule]); + useEffect(() => { + if (activeModule !== "simulation") setSubModule("properties"); + if (activeModule === "simulation") setSubModule("simulations"); + }, [activeModule, setSubModule]); - useEffect(() => { - if ( - activeModule !== "mechanics" && - selectedEventData && - selectedEventSphere - ) { - setSubModule("mechanics"); - } else if (!selectedEventData && !selectedEventSphere) { - if (activeModule === "simulation") { - setSubModule("simulations"); - } - } - if (activeModule !== "simulation") { - setSubModule("properties"); - } - }, [activeModule, selectedEventData, selectedEventSphere, setSubModule]); - - useEffect(() => { - if (activeModule === "visualization") { - setDisplayComponent("visualization"); - return; - } - - if (!isVersionSaved && activeModule === "simulation") { - if (subModule === "simulations") { - setDisplayComponent("simulations"); - return; - } - if (subModule === "mechanics") { - setDisplayComponent("mechanics"); - return; - } - if (subModule === "analysis") { - setDisplayComponent("analysis"); - return; - } - if (subModule === "resourceManagement") { - setDisplayComponent("resourceManagement"); - return; - } - } - - if (activeModule === "simulation" || activeModule === "builder") { - if (subModule === "resourceManagement") { - setDisplayComponent("resourceManagement"); - return; - } - } - - if (subModule === "properties" && activeModule !== "visualization") { - if (selectedFloorItem) { - setDisplayComponent("assetProperties"); - return; - } - if ( - !selectedFloorItem && - !selectedFloor && - !selectedAisle && - selectedWall - ) { - setDisplayComponent("selectedWallProperties"); - return; - } - if ( - !selectedFloorItem && - !selectedWall && - !selectedAisle && - selectedFloor - ) { - setDisplayComponent("selectedFloorProperties"); - return; - } - if (viewVersionHistory) { - setDisplayComponent("versionHistory"); - return; - } - if (selectedSubCategory) { - setDisplayComponent("selectedDecalProperties"); - return; - } - if ( - !selectedFloorItem && - !selectedFloor && - !selectedWall && - !selectedSubCategory - ) { - if (toolMode === "Aisle") { - setDisplayComponent("aisleProperties"); - return; + useEffect(() => { + if (activeModule !== "mechanics" && selectedEventData && selectedEventSphere) { + setSubModule("mechanics"); + } else if (!selectedEventData && !selectedEventSphere) { + if (activeModule === "simulation") { + setSubModule("simulations"); + } } - if (toolMode === "Wall") { - setDisplayComponent("wallProperties"); - return; + if (activeModule !== "simulation") { + setSubModule("properties"); } - if (toolMode === "Floor") { - setDisplayComponent("floorProperties"); - return; + }, [activeModule, selectedEventData, selectedEventSphere, setSubModule]); + + useEffect(() => { + if (activeModule === "visualization") { + setDisplayComponent("visualization"); + return; } - setDisplayComponent("globalProperties"); - return; - } - } - if ( - subModule === "zoneProperties" && - (activeModule === "builder" || activeModule === "simulation") - ) { - setDisplayComponent("zoneProperties"); - return; - } + if (!isVersionSaved && activeModule === "simulation") { + if (subModule === "simulations") { + setDisplayComponent("simulations"); + return; + } + if (subModule === "mechanics") { + setDisplayComponent("mechanics"); + return; + } + if (subModule === "analysis") { + setDisplayComponent("analysis"); + return; + } + if (subModule === "resourceManagement") { + setDisplayComponent("resourceManagement"); + return; + } + } - setDisplayComponent("none"); - }, [ - viewVersionHistory, - activeModule, - subModule, - isVersionSaved, - selectedFloorItem, - selectedWall, - selectedFloor, - selectedAisle, - toolMode, - selectedSubCategory, - ]); + if (activeModule === "simulation" || activeModule === "builder") { + if (subModule === "resourceManagement") { + setDisplayComponent("resourceManagement"); + return; + } + } - const renderComponent = () => { - switch (displayComponent) { - case "versionHistory": - return ; - case "globalProperties": - return ; - case "aisleProperties": - return ; - case "wallProperties": - return ; - case "floorProperties": - return ; - case "assetProperties": - return ; - case "selectedWallProperties": - return ; - case "selectedFloorProperties": - return ; - case "zoneProperties": - return ; - case "simulations": - return ; - case "mechanics": - return ; - case "analysis": - return ; - case "visualization": - return ; - case "selectedDecalProperties": - return ; - case "resourceManagement": - return ; - default: - return null; - } - }; + if (subModule === "properties" && activeModule !== "visualization") { + if (selectedFloorItem) { + setDisplayComponent("assetProperties"); + return; + } + if (!selectedFloorItem && !selectedFloor && !selectedAisle && selectedWall) { + setDisplayComponent("selectedWallProperties"); + return; + } + if (!selectedFloorItem && !selectedWall && !selectedAisle && selectedFloor) { + setDisplayComponent("selectedFloorProperties"); + return; + } + if (viewVersionHistory) { + setDisplayComponent("versionHistory"); + return; + } + if (selectedDecal) { + setDisplayComponent("selectedDecalProperties"); + return; + } + if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal) { + if (toolMode === "Aisle") { + setDisplayComponent("aisleProperties"); + return; + } + if (toolMode === "Wall") { + setDisplayComponent("wallProperties"); + return; + } + if (toolMode === "Floor") { + setDisplayComponent("floorProperties"); + return; + } + setDisplayComponent("globalProperties"); + return; + } + } - return ( -
-
- {toggleUIRight && ( - <> - {(!isVersionSaved || activeModule !== "simulation") && ( -
- {activeModule !== "simulation" && ( + if (subModule === "zoneProperties" && (activeModule === "builder" || activeModule === "simulation")) { + setDisplayComponent("zoneProperties"); + return; + } + + setDisplayComponent("none"); + }, [viewVersionHistory, activeModule, subModule, isVersionSaved, selectedFloorItem, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal]); + + const renderComponent = () => { + switch (displayComponent) { + case "versionHistory": + return ; + case "globalProperties": + return ; + case "aisleProperties": + return ; + case "wallProperties": + return ; + case "floorProperties": + return ; + case "assetProperties": + return ; + case "selectedWallProperties": + return ; + case "selectedFloorProperties": + return ; + case "zoneProperties": + return ; + case "simulations": + return ; + case "mechanics": + return ; + case "analysis": + return ; + case "visualization": + return ; + case "selectedDecalProperties": + return ; + case "resourceManagement": + return ; + default: + return null; + } + }; + + return ( +
+
+ {toggleUIRight && ( <> - + {(!isVersionSaved || activeModule !== "simulation") && ( +
+ {activeModule !== "simulation" && ( + <> + + + )} + + {activeModule === "simulation" && ( + <> + + + + + )} + + {(activeModule === "builder" || + activeModule === "simulation") && ( + + )} +
+ )} + + {displayComponent !== "none" && ( +
+
+ {renderComponent()} + {/* */} +
+
+ )} - )} - - {activeModule === "simulation" && ( - <> - - - - - )} - - {(activeModule === "builder" || - activeModule === "simulation") && ( - - )} -
- )} - - {displayComponent !== "none" && ( -
-
- {renderComponent()} - {/* */} -
-
- )} - - )} -
- ); + )} +
+ ); }; export default SideBarRight; diff --git a/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx b/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx index 962e967..ccddafa 100644 --- a/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx +++ b/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx @@ -1,30 +1,37 @@ import React from "react"; interface RotationInputProps { + heading?: string; // Optional label for the input + label?: string; // Optional label for the input onChange: (value: string) => void; // Callback for value change placeholder?: string; // Optional placeholder type?: string; // Input type (e.g., text, number, email) value?: number; + disabled?: boolean; // Disable the input if true } const RotationInput: React.FC = ({ + label = "Rotate :", // Default label + heading = "Rotation", // Default heading onChange, placeholder = "Enter value", // Default placeholder type = "number", // Default type value = "number", + disabled = false, }) => { return (
-
Rotation
+
{heading}
-
Rotate :
+
{label}
onChange(e.target.value)} placeholder={placeholder} value={value} + disabled={disabled} />
diff --git a/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx b/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx index 9c8b979..3a36e6c 100644 --- a/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx @@ -57,6 +57,7 @@ const AssetProperties: React.FC = () => {
{objectPosition && ( { }} value1={parseFloat(objectPosition.x.toFixed(5))} value2={parseFloat(objectPosition.z.toFixed(5))} @@ -64,6 +65,7 @@ const AssetProperties: React.FC = () => { )} {objectRotation && ( { }} value={parseFloat(objectRotation.y.toFixed(5))} /> diff --git a/app/src/components/layout/sidebarRight/properties/DecalProperties.tsx b/app/src/components/layout/sidebarRight/properties/DecalProperties.tsx deleted file mode 100644 index 4163ea5..0000000 --- a/app/src/components/layout/sidebarRight/properties/DecalProperties.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { - LayeringBottomIcon, - LayeringTopIcon, -} from "../../../icons/ExportCommonIcons"; -import InputRange from "../../../ui/inputs/InputRange"; -import RotationInput from "../customInput/RotationInput"; -import Vector3Input from "../customInput/Vector3Input"; - -const DecalProperties = () => { - return ( -
-
Decal Propertis
-
- {}} - value={10} - /> - console.log(value)} - header="Scale" - value={[0, 0, 0] as [number, number, number]} - /> -
- -
- console.log(value)} - key={"6"} - /> - -
-
Layering
- -
- - -
-
-
-
- ); -}; - -export default DecalProperties; diff --git a/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx b/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx new file mode 100644 index 0000000..1db536b --- /dev/null +++ b/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx @@ -0,0 +1,49 @@ +import { LayeringBottomIcon, LayeringTopIcon } from "../../../icons/ExportCommonIcons"; +import InputRange from "../../../ui/inputs/InputRange"; +import RotationInput from "../customInput/RotationInput"; + +const SelectedDecalProperties = () => { + return ( +
+
Decal Properties
+
+ { }} + value={10} + /> + { }} + value={10} + /> +
+ +
+ console.log(value)} + /> + +
+
Layering
+ +
+ + +
+
+
+
+ ); +}; + +export default SelectedDecalProperties; diff --git a/app/src/modules/builder/Decal/decalInstance.tsx b/app/src/modules/builder/Decal/decalInstance.tsx index 1b68f3d..69b0c7c 100644 --- a/app/src/modules/builder/Decal/decalInstance.tsx +++ b/app/src/modules/builder/Decal/decalInstance.tsx @@ -1,33 +1,132 @@ import * as THREE from 'three'; import { Decal } from '@react-three/drei' import { useLoader } from '@react-three/fiber'; -import { useToggleView } from '../../../store/builder/store'; +import { useSocketStore, useToggleView, useToolMode } from '../../../store/builder/store'; import { useBuilderStore } from '../../../store/builder/useBuilderStore'; import defaultMaterial from '../../../assets/textures/floor/wall-tex.png'; import useModuleStore from '../../../store/useModuleStore'; +import { useSceneContext } from '../../scene/sceneContext'; +import { useEffect } from 'react'; +import { getUserData } from '../../../functions/getUserData'; +import { useVersionContext } from '../version/versionContext'; +import { useParams } from 'react-router-dom'; -function DecalInstance({ visible = true, decal, zPosition = decal.decalPosition[2] }: { visible?: boolean, decal: Decal, zPosition?: number }) { - const { setSelectedWall, setSelectedFloor, selectedDecal, setSelectedDecal } = useBuilderStore(); - const { togglView } = useToggleView(); +// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi'; +// import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi'; + +function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalPosition[2] }: { parent: Wall | Floor; visible?: boolean, decal: Decal, zPosition?: number }) { + const { setSelectedWall, setSelectedFloor, selectedDecal, deletableDecal, setSelectedDecal, setDeletableDecal } = useBuilderStore(); + const { wallStore, floorStore } = useSceneContext(); + const { removeDecal: removeDecalFromWall } = wallStore(); + const { removeDecal: removeDecalFromFloor } = floorStore(); + const { toolMode } = useToolMode(); + const { toggleView } = useToggleView(); const { activeModule } = useModuleStore(); + const { userId, organization } = getUserData(); + const { selectedVersionStore } = useVersionContext(); + const { selectedVersion } = selectedVersionStore(); + const { projectId } = useParams(); + const { socket } = useSocketStore(); const material = useLoader(THREE.TextureLoader, defaultMaterial); + useEffect(() => { + if (!toggleView && activeModule === 'builder') { + if (toolMode !== 'cursor') { + if (selectedDecal) setSelectedDecal(null); + } + if (toolMode !== '3D-Delete') { + if (deletableDecal) setDeletableDecal(null); + } + } else { + if (selectedDecal) setSelectedDecal(null); + if (deletableDecal) setDeletableDecal(null); + } + }, [toggleView, toolMode, activeModule, selectedDecal, deletableDecal]); + + const deleteDecal = (decalUuid: string, parent: Wall | Floor) => { + if ('wallUuid' in parent) { + const updatedWall = removeDecalFromWall(decalUuid); + + if (projectId && updatedWall) { + // API + + // upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall); + + // SOCKET + + const data = { + wallData: updatedWall, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + + socket.emit('v1:model-Wall:add', data); + } + } else if ('floorUuid' in parent) { + const updatedFloor = removeDecalFromFloor(decalUuid); + + if (projectId && updatedFloor) { + // API + + // upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor); + + // SOCKET + + const data = { + floorData: updatedFloor, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + + socket.emit('v1:model-Floor:add', data); + } + } + } + return ( { - if (visible && !togglView && activeModule === 'builder') { + if (visible && !toggleView && activeModule === 'builder') { if (e.object.userData.decalUuid) { e.stopPropagation(); - setSelectedDecal(e.object); - setSelectedWall(null); - setSelectedFloor(null); + if (toolMode === 'cursor') { + setSelectedDecal(e.object); + setSelectedWall(null); + setSelectedFloor(null); + } else if (toolMode === '3D-Delete') { + deleteDecal(e.object.userData.decalUuid, parent); + } + } + } + }} + onPointerEnter={(e) => { + if (visible && !toggleView && activeModule === 'builder') { + if (e.object.userData.decalUuid) { + e.stopPropagation(); + if (toolMode === '3D-Delete') { + setDeletableDecal(e.object); + } + } + } + }} + onPointerLeave={(e) => { + if (visible && !toggleView && activeModule === 'builder') { + if (e.object.userData.decalUuid) { + e.stopPropagation(); + if (toolMode === '3D-Delete' && deletableDecal && deletableDecal?.userData.decalUuid === e.object.userData.decalUuid) { + setDeletableDecal(null); + } } } }} diff --git a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx index aa60691..f89b38d 100644 --- a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx +++ b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx @@ -28,7 +28,7 @@ import material4MetalicMap from "../../../../../assets/textures/floor/tex3/metal import material4NormalMap from "../../../../../assets/textures/floor/tex3/metal_plate_nor_gl_1k.png"; function FloorInstance({ floor }: { floor: Floor }) { - const { togglView } = useToggleView(); + const { toggleView } = useToggleView(); const { activeModule } = useModuleStore(); const { selectedFloor, setSelectedFloor, setSelectedDecal } = useBuilderStore(); const savedTheme = localStorage.getItem("theme"); @@ -159,7 +159,7 @@ function FloorInstance({ floor }: { floor: Floor }) { position={[0, !floor.isBeveled ? floor.floorDepth - 0.1 : floor.floorDepth - 0.2, 0,]} userData={floor} onDoubleClick={(e) => { - if (!togglView && activeModule === "builder") { + if (!toggleView && activeModule === "builder") { if (e.object.userData.floorUuid) { e.stopPropagation(); setSelectedFloor(e.object); diff --git a/app/src/modules/builder/floor/Instances/floorInstances.tsx b/app/src/modules/builder/floor/Instances/floorInstances.tsx index a578800..2af5787 100644 --- a/app/src/modules/builder/floor/Instances/floorInstances.tsx +++ b/app/src/modules/builder/floor/Instances/floorInstances.tsx @@ -2,21 +2,36 @@ import React, { useEffect, useMemo } from 'react'; import { Vector3 } from 'three'; import { Html } from '@react-three/drei'; import { useSceneContext } from '../../../scene/sceneContext'; -import { useToggleView } from '../../../../store/builder/store'; +import { useToggleView, useToolMode } from '../../../../store/builder/store'; import Line from '../../line/line'; import Point from '../../point/point'; import FloorInstance from './Instance/floorInstance'; import Floor2DInstance from './Instance/floor2DInstance'; +import useModuleStore from '../../../../store/useModuleStore'; +import { useBuilderStore } from '../../../../store/builder/useBuilderStore'; function FloorInstances() { const { floorStore } = useSceneContext(); const { floors } = floorStore(); + const { setSelectedFloor, selectedFloor } = useBuilderStore(); + const { toolMode } = useToolMode(); const { toggleView } = useToggleView(); + const { activeModule } = useModuleStore(); useEffect(() => { // console.log('floors: ', floors); }, [floors]) + useEffect(() => { + if (!toggleView && activeModule === 'builder') { + if (toolMode !== 'cursor') { + if (selectedFloor) setSelectedFloor(null); + } + } else { + if (selectedFloor) setSelectedFloor(null); + } + }, [toggleView, toolMode, activeModule, selectedFloor]); + const allPoints = useMemo(() => { const points: Point[] = []; const seenUuids = new Set(); diff --git a/app/src/modules/builder/floor/floorGroup.tsx b/app/src/modules/builder/floor/floorGroup.tsx index 47ea3b5..d782e1a 100644 --- a/app/src/modules/builder/floor/floorGroup.tsx +++ b/app/src/modules/builder/floor/floorGroup.tsx @@ -10,7 +10,7 @@ import FloorInstances from './Instances/floorInstances'; import { getFloorsApi } from '../../../services/factoryBuilder/floor/getFloorsApi'; function FloorGroup() { - const { togglView } = useToggleView(); + const { toggleView } = useToggleView(); const { setSelectedFloor, setSelectedDecal } = useBuilderStore(); const { activeModule } = useModuleStore(); const { activeTool } = useActiveTool(); @@ -21,11 +21,11 @@ function FloorGroup() { const { projectId } = useParams(); useEffect(() => { - if (togglView || activeModule !== 'builder') { + if (toggleView || activeModule !== 'builder') { setSelectedFloor(null); setSelectedDecal(null); } - }, [togglView, activeModule, activeTool]) + }, [toggleView, activeModule, activeTool]) useEffect(() => { if (projectId && selectedVersion) { diff --git a/app/src/modules/builder/wall/Instances/instance/wall.tsx b/app/src/modules/builder/wall/Instances/instance/wall.tsx index 8798b01..939dc78 100644 --- a/app/src/modules/builder/wall/Instances/instance/wall.tsx +++ b/app/src/modules/builder/wall/Instances/instance/wall.tsx @@ -17,11 +17,11 @@ import material1 from '../../../../../assets/textures/floor/factory wall texture function Wall({ wall }: { readonly wall: Wall }) { const { wallStore, wallAssetStore } = useSceneContext(); - const { walls } = wallStore(); + const { walls, addDecal } = wallStore(); const { wallAssets, getWallAssetsByWall, setVisibility } = wallAssetStore(); const assets = getWallAssetsByWall(wall.wallUuid); const { selectedWall, setSelectedWall, setSelectedDecal } = useBuilderStore(); - const { togglView } = useToggleView(); + const { toggleView } = useToggleView(); const { activeModule } = useModuleStore(); const { camera } = useThree(); const { wallVisibility } = useWallVisibility(); @@ -154,11 +154,23 @@ function Wall({ wall }: { readonly wall: Wall }) { userData={wall} name={`WallReference_${wall.wallUuid}`} onDoubleClick={(e) => { - if (visible && !togglView && activeModule === 'builder') { + if (visible && !toggleView && activeModule === 'builder') { if (e.object.userData.wallUuid) { e.stopPropagation(); setSelectedWall(e.object); setSelectedDecal(null); + + if (wall.decals.length > 0) return; + const decal: Decal = { + decalUuid: THREE.MathUtils.generateUUID(), + decalName: 'Decal', + decalId: 'Default Decal', + decalPosition: [0, 0, wall.wallThickness / 2 + 0.001], + decalRotation: 0, + decalScale: 1, + decalType: { type: 'Wall', wallUuid: wall.wallUuid } + } + addDecal(wall.wallUuid, decal); } } }} @@ -171,7 +183,7 @@ function Wall({ wall }: { readonly wall: Wall }) { {wall.decals.map((decal) => ( - + ))} diff --git a/app/src/modules/builder/wall/Instances/wallInstances.tsx b/app/src/modules/builder/wall/Instances/wallInstances.tsx index 254705a..a67e3a3 100644 --- a/app/src/modules/builder/wall/Instances/wallInstances.tsx +++ b/app/src/modules/builder/wall/Instances/wallInstances.tsx @@ -2,8 +2,9 @@ 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 } from '../../../../store/builder/store'; +import { useToggleView, useToolMode } from '../../../../store/builder/store'; import { useWallClassification } from './instance/helpers/useWallClassification'; import Line from '../../line/line'; import Point from '../../point/point'; @@ -12,17 +13,31 @@ 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/useModuleStore'; 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); - const { toggleView } = useToggleView(); 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(); diff --git a/app/src/modules/builder/wall/wallGroup.tsx b/app/src/modules/builder/wall/wallGroup.tsx index 084b969..3561751 100644 --- a/app/src/modules/builder/wall/wallGroup.tsx +++ b/app/src/modules/builder/wall/wallGroup.tsx @@ -11,7 +11,7 @@ import WallInstances from './Instances/wallInstances'; import { getWallsApi } from '../../../services/factoryBuilder/wall/getWallsApi'; function WallGroup() { - const { togglView } = useToggleView(); + const { toggleView } = useToggleView(); const { setSelectedWall, setSelectedDecal } = useBuilderStore(); const { activeModule } = useModuleStore(); const { activeTool } = useActiveTool(); @@ -22,11 +22,11 @@ function WallGroup() { const { projectId } = useParams(); useEffect(() => { - if (togglView || activeModule !== 'builder') { + if (toggleView || activeModule !== 'builder') { setSelectedWall(null); setSelectedDecal(null); } - }, [togglView, activeModule, activeTool]) + }, [toggleView, activeModule, activeTool]) useEffect(() => { if (projectId && selectedVersion) { diff --git a/app/src/modules/builder/wallAsset/wallAssetCreator.tsx b/app/src/modules/builder/wallAsset/wallAssetCreator.tsx index fb95236..13438c2 100644 --- a/app/src/modules/builder/wallAsset/wallAssetCreator.tsx +++ b/app/src/modules/builder/wallAsset/wallAssetCreator.tsx @@ -14,7 +14,7 @@ import closestPointOnLineSegment from '../line/helpers/getClosestPointOnLineSegm function WallAssetCreator() { const { socket } = useSocketStore(); const { pointer, camera, raycaster, scene, gl } = useThree(); - const { togglView } = useToggleView(); + const { toggleView } = useToggleView(); const { activeModule } = useModuleStore(); const { wallAssetStore } = useSceneContext(); const { addWallAsset } = wallAssetStore(); @@ -84,7 +84,7 @@ function WallAssetCreator() { } }; - if (!togglView && activeModule === 'builder') { + if (!toggleView && activeModule === 'builder') { canvasElement.addEventListener('drop', onDrop); } @@ -92,7 +92,7 @@ function WallAssetCreator() { canvasElement.removeEventListener('drop', onDrop); }; - }, [gl, camera, togglView, activeModule, socket, selectedItem, setSelectedItem]); + }, [gl, camera, toggleView, activeModule, socket, selectedItem, setSelectedItem]); return ( <> diff --git a/app/src/modules/builder/wallAsset/wallAssetGroup.tsx b/app/src/modules/builder/wallAsset/wallAssetGroup.tsx index bae9f87..95e2e90 100644 --- a/app/src/modules/builder/wallAsset/wallAssetGroup.tsx +++ b/app/src/modules/builder/wallAsset/wallAssetGroup.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { useActiveTool, useToggleView } from '../../../store/builder/store'; +import { useToggleView, useToolMode } from '../../../store/builder/store'; import { useBuilderStore } from '../../../store/builder/useBuilderStore'; import { useVersionContext } from '../version/versionContext'; import { useSceneContext } from '../../scene/sceneContext'; @@ -10,10 +10,10 @@ import WallAssetInstances from './Instances/wallAssetInstances' import { getWallAssetsApi } from '../../../services/factoryBuilder/asset/wallAsset/getWallAssetsApi'; function WallAssetGroup() { - const { togglView } = useToggleView(); - const { setSelectedFloorAsset, setDeletableWallAsset } = useBuilderStore(); + const { toggleView } = useToggleView(); + const { setSelectedWallAsset, setDeletableWallAsset } = useBuilderStore(); const { activeModule } = useModuleStore(); - const { activeTool } = useActiveTool(); + const { toolMode } = useToolMode(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); const { wallAssetStore } = useSceneContext(); @@ -21,11 +21,11 @@ function WallAssetGroup() { const { projectId } = useParams(); useEffect(() => { - if (togglView || activeModule !== 'builder') { - setSelectedFloorAsset(null); + if (toggleView || activeModule !== 'builder' || toolMode !== 'cursor') { + setSelectedWallAsset(null); } setDeletableWallAsset(null); - }, [togglView, activeModule, activeTool]) + }, [toggleView, activeModule, toolMode]) useEffect(() => { if (projectId && selectedVersion) { diff --git a/app/src/modules/builder/zone/zoneGroup.tsx b/app/src/modules/builder/zone/zoneGroup.tsx index c44bf09..08d3e9c 100644 --- a/app/src/modules/builder/zone/zoneGroup.tsx +++ b/app/src/modules/builder/zone/zoneGroup.tsx @@ -11,7 +11,7 @@ import ZoneInstances from './Instances/zoneInstances'; import { getZonesApi } from '../../../services/factoryBuilder/zone/getZonesApi'; function ZoneGroup() { - const { togglView } = useToggleView(); + const { toggleView } = useToggleView(); const { setSelectedZone } = useBuilderStore(); const { activeModule } = useModuleStore(); const { activeTool } = useActiveTool(); @@ -22,10 +22,10 @@ function ZoneGroup() { const { projectId } = useParams(); useEffect(() => { - if (togglView || activeModule !== 'builder') { + if (toggleView || activeModule !== 'builder') { setSelectedZone(null); } - }, [togglView, activeModule, activeTool]) + }, [toggleView, activeModule, activeTool]) useEffect(() => { if (projectId && selectedVersion) { diff --git a/app/src/modules/scene/postProcessing/postProcessing.tsx b/app/src/modules/scene/postProcessing/postProcessing.tsx index 8aacd96..5558f9d 100644 --- a/app/src/modules/scene/postProcessing/postProcessing.tsx +++ b/app/src/modules/scene/postProcessing/postProcessing.tsx @@ -1,25 +1,19 @@ -import { DepthOfField, Bloom, EffectComposer, N8AO, Outline } from "@react-three/postprocessing"; -import { useThree } from "@react-three/fiber"; -import { BlendFunction } from "postprocessing"; -import { - useDeletableFloorItem, - useSelectedWallItem, - useSelectedFloorItem, -} from "../../../store/builder/store"; -import * as CONSTANTS from "../../../types/world/worldConstants"; -import { useDeletableEventSphere, useSelectedEventSphere, useSelectedPoints } from "../../../store/simulation/useSimulationStore"; import { useEffect } from "react"; +import { BlendFunction } from "postprocessing"; +import { DepthOfField, Bloom, EffectComposer, N8AO, Outline } from "@react-three/postprocessing"; +import { useDeletableFloorItem, useSelectedWallItem, useSelectedFloorItem, } from "../../../store/builder/store"; +import { useDeletableEventSphere, useSelectedEventSphere, useSelectedPoints } from "../../../store/simulation/useSimulationStore"; import { useBuilderStore } from "../../../store/builder/useBuilderStore"; +import * as CONSTANTS from "../../../types/world/worldConstants"; export default function PostProcessing() { - const { scene } = useThree(); const { selectedPoints } = useSelectedPoints(); const { deletableFloorItem } = useDeletableFloorItem(); const { selectedWallItem } = useSelectedWallItem(); const { selectedFloorItem } = useSelectedFloorItem(); const { selectedEventSphere } = useSelectedEventSphere(); const { deletableEventSphere } = useDeletableEventSphere(); - const { selectedAisle, selectedWall, selectedDecal, selectedFloor, selectedWallAsset, deletableWallAsset } = useBuilderStore(); + const { selectedAisle, selectedWall, selectedDecal, selectedFloor, selectedWallAsset, deletableWallAsset, deletableDecal } = useBuilderStore(); function flattenChildren(children: any[]) { const allChildren: any[] = []; @@ -68,6 +62,10 @@ export default function PostProcessing() { // console.log('selectedPoints: ', selectedPoints); }, [selectedPoints]) + useEffect(() => { + // console.log('deletableDecal: ', deletableDecal); + }, [deletableDecal]) + return ( )} + {deletableDecal && ( + + )} {deletableFloorItem && ( ((set: any, get: any) => ({ // }); // }, // })); + export const useLoadingProgress = create<{ loadingProgress: number; setLoadingProgress: (x: number) => void; diff --git a/app/src/store/builder/useBuilderStore.ts b/app/src/store/builder/useBuilderStore.ts index 5be4e3b..d6176f7 100644 --- a/app/src/store/builder/useBuilderStore.ts +++ b/app/src/store/builder/useBuilderStore.ts @@ -39,6 +39,7 @@ interface BuilderState { // Decal Settings selectedDecal: Object3D | null; + deletableDecal: Object3D | null; // Aisle General selectedAisle: Object3D | null; @@ -87,6 +88,7 @@ interface BuilderState { // Setters - Decal setSelectedDecal: (decal: Object3D | null) => void; + setDeletableDecal: (decal: Object3D | null) => void; // Setters - Aisle General setSelectedAisle: (aisle: Object3D | null) => void; @@ -140,6 +142,7 @@ export const useBuilderStore = create()( zoneColor: 'blue', selectedDecal: null, + deletableDecal: null, selectedAisle: null, aisleType: 'solid-aisle', @@ -293,6 +296,12 @@ export const useBuilderStore = create()( }) }, + setDeletableDecal: (decal: Object3D | null) => { + set((state) => { + state.deletableDecal = decal; + }) + }, + // === Setters: Aisle General === setSelectedAisle: (aisle: Object3D | null) => { diff --git a/app/src/store/builder/useFloorStore.ts b/app/src/store/builder/useFloorStore.ts index a045884..6f488a5 100644 --- a/app/src/store/builder/useFloorStore.ts +++ b/app/src/store/builder/useFloorStore.ts @@ -21,7 +21,7 @@ interface FloorStore { setMaterial: (uuid: string, sideMaterial: string, topMaterial: string) => void; addDecal: (floors: string, decal: Decal) => void; updateDecal: (decalUuid: string, decal: Decal) => void; - removeDecal: (decalUuid: string) => void; + removeDecal: (decalUuid: string) => Floor | undefined; updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void; updateDecalRotation: (decalUuid: string, rotation: number) => void; updateDecalScale: (decalUuid: string, scale: number) => void; @@ -213,11 +213,19 @@ export const createFloorStore = () => { } }), - removeDecal: (decalUuid) => set(state => { - for (const floor of state.floors) { - floor.decals = floor.decals.filter(d => d.decalUuid !== decalUuid); - } - }), + removeDecal: (decalUuid) => { + let affectedFloor: Floor | undefined; + set(state => { + for (const floor of state.floors) { + const hasDecal = floor.decals.some(d => d.decalUuid === decalUuid); + if (hasDecal) { + floor.decals = floor.decals.filter(d => d.decalUuid !== decalUuid); + affectedFloor = JSON.parse(JSON.stringify(floor)); + } + } + }); + return affectedFloor; + }, updateDecalPosition: (decalUuid, position) => set(state => { for (const floor of state.floors) { diff --git a/app/src/store/builder/useWallStore.ts b/app/src/store/builder/useWallStore.ts index db40269..92b6fe5 100644 --- a/app/src/store/builder/useWallStore.ts +++ b/app/src/store/builder/useWallStore.ts @@ -11,7 +11,7 @@ interface WallStore { removeWallByPoints: (Points: [Point, Point]) => Wall | undefined; addDecal: (wallUuid: string, decal: Decal) => void; updateDecal: (decalUuid: string, decal: Decal) => void; - removeDecal: (decalUuid: string) => void; + removeDecal: (decalUuid: string) => Wall | undefined; updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void; updateDecalRotation: (decalUuid: string, rotation: number) => void; updateDecalScale: (decalUuid: string, scale: number) => void; @@ -99,11 +99,19 @@ export const createWallStore = () => { } }), - removeDecal: (decalUuid) => set((state) => { - for (const wall of state.walls) { - wall.decals = wall.decals.filter(d => d.decalUuid !== decalUuid); - } - }), + removeDecal: (decalUuid) => { + let affectedWall: Wall | undefined; + set((state) => { + for (const wall of state.walls) { + const hasDecal = wall.decals.some(d => d.decalUuid === decalUuid); + if (hasDecal) { + wall.decals = wall.decals.filter(d => d.decalUuid !== decalUuid); + affectedWall = JSON.parse(JSON.stringify(wall)); + } + } + }); + return affectedWall; + }, updateDecalPosition: (decalUuid, position) => set((state) => { for (const wall of state.walls) {