diff --git a/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx b/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx index ccddafa..1265d81 100644 --- a/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx +++ b/app/src/components/layout/sidebarRight/customInput/RotationInput.tsx @@ -1,23 +1,29 @@ 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) + heading?: string; + label?: string; + onChange: (value: string) => void; + placeholder?: string; + type?: string; value?: number; - disabled?: boolean; // Disable the input if true + disabled?: boolean; + min?: number; + max?: number; + step?: number; } const RotationInput: React.FC = ({ - label = "Rotate :", // Default label - heading = "Rotation", // Default heading + label = "Rotate :", + heading = "Rotation", onChange, - placeholder = "Enter value", // Default placeholder - type = "number", // Default type - value = "number", + placeholder = "Enter value", + type = "number", + value, disabled = false, + min, + max, + step, }) => { return (
@@ -32,6 +38,9 @@ const RotationInput: React.FC = ({ placeholder={placeholder} value={value} disabled={disabled} + min={min} + max={max} + step={step} />
diff --git a/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx b/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx index 1db536b..7994a1f 100644 --- a/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx @@ -1,42 +1,178 @@ +import { useParams } from "react-router-dom"; +import { useVersionContext } from "../../../../modules/builder/version/versionContext"; +import { useSceneContext } from "../../../../modules/scene/sceneContext"; +import { useBuilderStore } from "../../../../store/builder/useBuilderStore"; import { LayeringBottomIcon, LayeringTopIcon } from "../../../icons/ExportCommonIcons"; +import { useSocketStore } from "../../../../store/builder/store"; import InputRange from "../../../ui/inputs/InputRange"; import RotationInput from "../customInput/RotationInput"; +import { getUserData } from "../../../../functions/getUserData"; +// import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi"; +// import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi"; + const SelectedDecalProperties = () => { + const { selectedDecal, setSelectedDecal } = useBuilderStore(); + const { wallStore, floorStore } = useSceneContext(); + const { updateDecal: updateDecalFromWall } = wallStore(); + const { updateDecal: updateDecalFromFloor } = floorStore(); + const { userId, organization } = getUserData(); + const { selectedVersionStore } = useVersionContext(); + const { selectedVersion } = selectedVersionStore(); + const { projectId } = useParams(); + const { socket } = useSocketStore(); + + const updateBackend = (updatedData: Wall | Floor) => { + if ('wallUuid' in updatedData) { + if (projectId && updatedData) { + // API + + // upsertWallApi(projectId, selectedVersion?.versionId || '', updatedData); + + // SOCKET + + const data = { + wallData: updatedData, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + + socket.emit('v1:model-Wall:add', data); + } + } else if ('floorUuid' in updatedData) { + if (projectId && updatedData) { + // API + + // upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedData); + + // SOCKET + + const data = { + floorData: updatedData, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + + socket.emit('v1:model-Floor:add', data); + } + } + } + + const handleRotationChange = (value: number) => { + if (!selectedDecal) return; + const updatedDecal = { ...selectedDecal.decalData, decalRotation: value }; + setSelectedDecal({ ...selectedDecal, decalData: updatedDecal }); + + if ('wallUuid' in selectedDecal.decalData.decalType) { + const updatedWall = updateDecalFromWall(updatedDecal.decalUuid, updatedDecal); + if (updatedWall) updateBackend(updatedWall); + } else if ('floorUuid' in selectedDecal.decalData.decalType) { + const updatedFloor = updateDecalFromFloor(updatedDecal.decalUuid, updatedDecal); + if (updatedFloor) updateBackend(updatedFloor); + } + } + + const handleScaleChange = (value: number) => { + if (!selectedDecal) return; + const updatedDecal = { ...selectedDecal.decalData, decalScale: value }; + setSelectedDecal({ ...selectedDecal, decalData: updatedDecal }); + + if ('wallUuid' in selectedDecal.decalData.decalType) { + const updatedWall = updateDecalFromWall(updatedDecal.decalUuid, updatedDecal); + if (updatedWall) updateBackend(updatedWall); + } else if ('floorUuid' in selectedDecal.decalData.decalType) { + const updatedFloor = updateDecalFromFloor(updatedDecal.decalUuid, updatedDecal); + if (updatedFloor) updateBackend(updatedFloor); + } + } + + const handleOpacityChange = (value: number) => { + if (!selectedDecal) return; + const updatedDecal = { ...selectedDecal.decalData, decalOpacity: value }; + setSelectedDecal({ ...selectedDecal, decalData: updatedDecal }); + + if ('wallUuid' in selectedDecal.decalData.decalType) { + const updatedWall = updateDecalFromWall(updatedDecal.decalUuid, updatedDecal); + if (updatedWall) updateBackend(updatedWall); + } else if ('floorUuid' in selectedDecal.decalData.decalType) { + const updatedFloor = updateDecalFromFloor(updatedDecal.decalUuid, updatedDecal); + if (updatedFloor) updateBackend(updatedFloor); + } + } + + const handleLayerChange = (direction: "up" | "down") => { + if (!selectedDecal) return; + + const position: [number, number, number] = [...(selectedDecal.decalData.decalPosition || [0, 0, 0]),]; + + if (direction === "up") { + position[2] = Math.abs(position[2]); + } else { + position[2] = -Math.abs(position[2]); + } + + const updatedDecal: Decal = { ...selectedDecal.decalData, decalPosition: position, }; + + setSelectedDecal({ ...selectedDecal, decalData: updatedDecal }); + + if ("wallUuid" in selectedDecal.decalData.decalType) { + const updatedWall = updateDecalFromWall(updatedDecal.decalUuid, updatedDecal); + if (updatedWall) updateBackend(updatedWall); + } else if ("floorUuid" in selectedDecal.decalData.decalType) { + const updatedFloor = updateDecalFromFloor(updatedDecal.decalUuid, updatedDecal); + if (updatedFloor) updateBackend(updatedFloor); + } + }; + + if (!selectedDecal) return null; + return (
Decal Properties
{ }} - value={10} + onChange={(e) => { handleRotationChange(parseFloat(e)) }} + value={selectedDecal.decalData.decalRotation || 0} /> { }} - value={10} + onChange={(e) => { handleScaleChange(parseFloat(e)) }} + value={selectedDecal.decalData.decalScale || 1} />
console.log(value)} + onChange={(value: number) => handleOpacityChange(value)} />
Layering
- -
diff --git a/app/src/modules/builder/Decal/decalInstance.tsx b/app/src/modules/builder/Decal/decalInstance.tsx index 69b0c7c..59f2141 100644 --- a/app/src/modules/builder/Decal/decalInstance.tsx +++ b/app/src/modules/builder/Decal/decalInstance.tsx @@ -93,7 +93,7 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP // debug visible={visible} position={[decal.decalPosition[0], decal.decalPosition[1], zPosition]} - rotation={[0, 0, 0]} + rotation={[0, 0, decal.decalRotation * (Math.PI / 180)]} scale={[decal.decalScale, decal.decalScale, 0.01]} userData={decal} onClick={(e) => { @@ -101,7 +101,7 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP if (e.object.userData.decalUuid) { e.stopPropagation(); if (toolMode === 'cursor') { - setSelectedDecal(e.object); + setSelectedDecal({ decalMesh: e.object, decalData: decal }); setSelectedWall(null); setSelectedFloor(null); } else if (toolMode === '3D-Delete') { @@ -131,7 +131,7 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP } }} onPointerMissed={() => { - if (selectedDecal && selectedDecal.userData.decalUuid === decal.decalUuid) { + if (selectedDecal && selectedDecal.decalMesh.userData.decalUuid === decal.decalUuid) { setSelectedDecal(null); } }} @@ -141,6 +141,8 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP side={THREE.DoubleSide} polygonOffset polygonOffsetFactor={-1} + transparent + opacity={decal.decalOpacity} /> ) diff --git a/app/src/modules/builder/wall/Instances/instance/wall.tsx b/app/src/modules/builder/wall/Instances/instance/wall.tsx index 939dc78..50d3536 100644 --- a/app/src/modules/builder/wall/Instances/instance/wall.tsx +++ b/app/src/modules/builder/wall/Instances/instance/wall.tsx @@ -167,6 +167,7 @@ function Wall({ wall }: { readonly wall: Wall }) { decalId: 'Default Decal', decalPosition: [0, 0, wall.wallThickness / 2 + 0.001], decalRotation: 0, + decalOpacity: 1, decalScale: 1, decalType: { type: 'Wall', wallUuid: wall.wallUuid } } @@ -183,7 +184,7 @@ function Wall({ wall }: { readonly wall: Wall }) { {wall.decals.map((decal) => ( - + ))} diff --git a/app/src/modules/scene/postProcessing/postProcessing.tsx b/app/src/modules/scene/postProcessing/postProcessing.tsx index 5558f9d..555c7a3 100644 --- a/app/src/modules/scene/postProcessing/postProcessing.tsx +++ b/app/src/modules/scene/postProcessing/postProcessing.tsx @@ -165,7 +165,7 @@ export default function PostProcessing() { )} {selectedDecal && ( void; // Setters - Decal - setSelectedDecal: (decal: Object3D | null) => void; + setSelectedDecal: (decal: { decalMesh: Object3D, decalData: Decal } | null) => void; setDeletableDecal: (decal: Object3D | null) => void; // Setters - Aisle General @@ -290,7 +290,7 @@ export const useBuilderStore = create()( // === Setters: Decal === - setSelectedDecal: (decal: Object3D | null) => { + setSelectedDecal: (decal: { decalMesh: Object3D, decalData: Decal } | null) => { set((state) => { state.selectedDecal = decal; }) diff --git a/app/src/store/builder/useFloorStore.ts b/app/src/store/builder/useFloorStore.ts index 6f488a5..c7b9545 100644 --- a/app/src/store/builder/useFloorStore.ts +++ b/app/src/store/builder/useFloorStore.ts @@ -20,7 +20,7 @@ interface FloorStore { setDepth: (uuid: string, depth: number) => void; setMaterial: (uuid: string, sideMaterial: string, topMaterial: string) => void; addDecal: (floors: string, decal: Decal) => void; - updateDecal: (decalUuid: string, decal: Decal) => void; + updateDecal: (decalUuid: string, decal: Decal) => Floor | undefined; removeDecal: (decalUuid: string) => Floor | undefined; updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void; updateDecalRotation: (decalUuid: string, rotation: number) => void; @@ -203,15 +203,20 @@ export const createFloorStore = () => { } }), - updateDecal: (decalUuid, updatedDecal) => set(state => { - for (const floor of state.floors) { - const index = floor.decals.findIndex(d => d.decalUuid === decalUuid); - if (index !== -1) { - floor.decals[index] = updatedDecal; - break; + updateDecal: (decalUuid, updatedDecal) => { + let affectedFloor: Floor | undefined; + set(state => { + for (const floor of state.floors) { + const index = floor.decals.findIndex(d => d.decalUuid === decalUuid); + if (index !== -1) { + floor.decals[index] = updatedDecal; + affectedFloor = JSON.parse(JSON.stringify(floor)); + break; + } } - } - }), + }) + return affectedFloor; + }, removeDecal: (decalUuid) => { let affectedFloor: Floor | undefined; diff --git a/app/src/store/builder/useWallStore.ts b/app/src/store/builder/useWallStore.ts index 92b6fe5..d1b2e86 100644 --- a/app/src/store/builder/useWallStore.ts +++ b/app/src/store/builder/useWallStore.ts @@ -10,7 +10,7 @@ interface WallStore { clearWalls: () => void; removeWallByPoints: (Points: [Point, Point]) => Wall | undefined; addDecal: (wallUuid: string, decal: Decal) => void; - updateDecal: (decalUuid: string, decal: Decal) => void; + updateDecal: (decalUuid: string, decal: Decal) => Wall | undefined; removeDecal: (decalUuid: string) => Wall | undefined; updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void; updateDecalRotation: (decalUuid: string, rotation: number) => void; @@ -90,14 +90,19 @@ export const createWallStore = () => { } }), - updateDecal: (decalUuid, decal) => set((state) => { - for (const wall of state.walls) { - const decalToUpdate = wall.decals.find(d => d.decalUuid === decalUuid); - if (decalToUpdate) { - Object.assign(decalToUpdate, decal); + updateDecal: (decalUuid, decal) => { + let affectedWall: Wall | undefined; + set((state) => { + for (const wall of state.walls) { + const decalToUpdate = wall.decals.find(d => d.decalUuid === decalUuid); + if (decalToUpdate) { + Object.assign(decalToUpdate, decal); + affectedWall = JSON.parse(JSON.stringify(wall)); + } } - } - }), + }); + return affectedWall; + }, removeDecal: (decalUuid) => { let affectedWall: Wall | undefined; diff --git a/app/src/types/builderTypes.d.ts b/app/src/types/builderTypes.d.ts index 3487fc6..e0440ec 100644 --- a/app/src/types/builderTypes.d.ts +++ b/app/src/types/builderTypes.d.ts @@ -88,6 +88,7 @@ interface Decal { decalType: WallDecal | FloorDecal; decalPosition: [number, number, number]; decalRotation: number; + decalOpacity: number; decalScale: number; }