From 92b1ba61973268f5232a5406fbd83bfbb0473aff Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Thu, 28 Aug 2025 16:01:16 +0530 Subject: [PATCH 1/3] decal bug fix --- app/src/modules/builder/Decal/decalCreator/decalCreator.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/modules/builder/Decal/decalCreator/decalCreator.tsx b/app/src/modules/builder/Decal/decalCreator/decalCreator.tsx index 221a2bf..35b54ce 100644 --- a/app/src/modules/builder/Decal/decalCreator/decalCreator.tsx +++ b/app/src/modules/builder/Decal/decalCreator/decalCreator.tsx @@ -15,7 +15,7 @@ import { getUserData } from '../../../../functions/getUserData'; function DecalCreator() { const { wallStore, floorStore } = useSceneContext(); const { addDecal: addDecalOnWall, getWallById } = wallStore(); - const { addDecal : addDecalOnFloor, getFloorById } = floorStore(); + const { addDecal: addDecalOnFloor, getFloorById } = floorStore(); const { droppedDecal } = useDroppedDecal(); const { activeModule } = useModuleStore(); const { userId, organization } = getUserData(); @@ -36,6 +36,7 @@ function DecalCreator() { const intersects = raycaster.intersectObjects(scene.children, true); const wallIntersect = intersects.find(i => i.object.userData && i.object.userData.wallUuid); const floorIntersect = intersects.find(i => i.object.userData && i.object.userData.floorUuid); + console.log('wallIntersect: ', wallIntersect); if (wallIntersect) { const wall = getWallById(wallIntersect.object.userData.wallUuid); @@ -51,7 +52,7 @@ function DecalCreator() { type: 'Wall', wallUuid: wallIntersect.object.userData.wallUuid, }, - decalPosition: [point.x, point.y, wall.wallThickness / 2 + 0.001], + decalPosition: [point.x, point.y, (wall.wallThickness / 2 + 0.001) * (wallIntersect.normal?.z || 1)], decalRotation: 0, decalOpacity: 1, decalScale: 1, From cb87cd067b5381ef12f3345c64452019efe48f5b Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Thu, 28 Aug 2025 16:32:45 +0530 Subject: [PATCH 2/3] added decal fallback --- .../assets/image/fallback/fallback decal 1.png | Bin 0 -> 19237 bytes .../assets/image/fallback/fallback decal.png | Bin 0 -> 2168 bytes .../Decal/decalInstance/decalInstance.tsx | 7 ++++--- 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 app/src/assets/image/fallback/fallback decal 1.png create mode 100644 app/src/assets/image/fallback/fallback decal.png diff --git a/app/src/assets/image/fallback/fallback decal 1.png b/app/src/assets/image/fallback/fallback decal 1.png new file mode 100644 index 0000000000000000000000000000000000000000..b47f4081ed66cb815cf3fcbed4ed4aabd033e83f GIT binary patch literal 19237 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 M07*qoM6N<$f*~=E_5c6? literal 0 HcmV?d00001 diff --git a/app/src/assets/image/fallback/fallback decal.png b/app/src/assets/image/fallback/fallback decal.png new file mode 100644 index 0000000000000000000000000000000000000000..b30e9fceb33ca45dbd3e03a326271f6478fc1543 GIT binary patch literal 2168 zcmbuB=Q|q;8^(i#*hHl291>eqNQ_#ih;T}W+G^C^RP9wowNa{ym^E9o_6`nODxDVE}-JWOlkE2mktl|t1ydV3aHzS+kJHmpx>8bdMBsI-!L3g{A!tGTPY+WiUq?>M| zEs~Wsv2QQ+UK$b*FlTV^m>Ddh-FWfj;h{QOdQ?6+`V-lnHsw;c^Bv{65sTUDMh!jD zifj$iy0|&kN4jsxsX$99bDVOSJKH_=t{Nz|FPw9;ijut7*D!cOR^nKKd8T(`3p6B2 zuX9U`ar|jYGQ8hnrQ=|_=w`&L_aI{qWW19H28v}b60qhWe)(TkixR_X0cyDcA#Z$g z2T}j@c^|oGXpzoF@{igv!c7sU*6euF-{yqsyhu)9B$VsGC^V~(Q4<~<5*9vov-5-y zpFy?`!rz|QC9?`eX_hT7N;L+k!ARnDE5hzAie5bHs4Ou;d=BZiHM=xh08BP4H?<0B^~Uct4^(v~D7 zWqvwMASm@W?_70pqSKz9PIG{(g)Hz{ryatgM;c;U+zc(uJZ*%08qp#kfzJerv1iRF zMUmD=9p~X3=k7U67WGovDwz-{ZF_MwVBVb2iQsW?axsck@l_F=RM#(Eyx}etM@%Z1 zLm-i0pa5LBgq)h~qF#xx64q*ce=d!*e=F7=CG%6q#)4<7GqoowM^MP*_Uk5>DI6#= zKjevCd%d&Y@_7jLvqTrU&_;oo9NX483igyTieAD~hA>6a> z-y&p%kFzZR)X`BQO4NCWs~^trYRUC2jU65n+L_3hW?dmlBZh};Exg3O$0AIzAu*bU zP7!x?{nd*Jv$WNGHMD}Ryj|Ty`KXkrSy#$xcdi3kQ-bzxx|=zm3#Yh+7nNnUYo0hB zDsbcSv((>q!2IW5#ZJ?wk|q<|UfKjp_NbMO-Z2UJ^Kj=HR11r9Fk| z0ZIN0>bUDwThEXLP wxY395jxvpJ)Yb9nF^oTf;>JoP`bmHl%DHH#GiF5yI!b$0eAM;6Cy3dD9l{D<)hWlmY!mS2h|tr*RA^i;y8W}|JS5&yD~ zEW0?{hC=vtC#wu?*y!KL(c~&wfDjuvux!0q7e1;Jg67PmI*&wEKH(Z=$Pa6tt%K*w zyf>rwiJ@y%jLhX9f?aMS4hSitU);T^}Jw(f(BMy)m(L1&Sc)R z1G+rO@T{H7c=jbn@mgasH$pYXc7@1`cW$ zVw5-Sd(0)uNaVh`SlO0>;Fwo0fA5?>88Sf3h1i<6xz;c#kr>RQvI*vuyH3*b@y(~H z=1C-RPmkdAXxuoBdw=ja@VcA1y|cB+a%#@<%&9-uat*DLExYTzZ$*e}Ucn?|t(Tim z8lEddcM^f+gkP^zu~%L7 zId{tFpHzLgh=o6R1$U02sX2-cg7+cQP4k>A;ndJX(M#=BpCaJd)%n% zUySEv!b=tDcnIB066;u-X<0kqDp!?51In>wqM=EHenHoTNSRnN{}l>MKdDZBphANu zMXy?E>WW*X-&?E5vZt2^ZIgM1-ihOWop7LsH8IG_J% z6)xk~+;5lXpp<4dd0Zu{Nq26cYR?MT@JGmeI>+bvw yj-SZqTe&3_+=Q;jzwPy73%)v_c6dV1Sk8KL=Jnc(cP<|VfPtQ&Zmo_(?0*4CZT#*4 literal 0 HcmV?d00001 diff --git a/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx b/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx index 8d0540a..f31dddd 100644 --- a/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx +++ b/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx @@ -4,9 +4,10 @@ import { useToggleView, useToolMode } from '../../../../store/builder/store'; import { useBuilderStore } from '../../../../store/builder/useBuilderStore'; import { retrieveImage, storeImage } from '../../../../utils/indexDB/idbUtils'; -import defaultMaterial from '../../../../assets/textures/floor/wall-tex.png'; +import defaultMaterial from '../../../../assets/image/fallback/fallback decal 1.png'; import useModuleStore from '../../../../store/useModuleStore'; import { useEffect, useRef, useState } from 'react'; + import { useDecalEventHandlers } from '../eventHandler/useDecalEventHandlers'; // import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi'; @@ -111,9 +112,9 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP console.error("Error storing texture in IndexedDB:", error); } }, - undefined, + undefined, (error) => { - console.error(`Error loading texture from backend:`, error); + echo.error(`Error loading texture from backend: ${decal.decalName}`); loadDefaultTexture(); } ); From 94bec4f2f0e36bbd7499fb9ad81e506a3dfa650e Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Thu, 28 Aug 2025 18:00:00 +0530 Subject: [PATCH 3/3] added selectedAisleProperties and its backend updation --- .../layout/sidebarRight/SideBarRight.tsx | 32 +- .../properties/SelectedAisleProperties.tsx | 545 ++++++++++++++++++ .../properties/SelectedDecalProperties.tsx | 23 +- .../instance/aisleTypes/arcAisle.tsx | 14 +- .../instance/aisleTypes/arrowAisle.tsx | 14 +- .../instance/aisleTypes/arrowsAisle.tsx | 14 +- .../instance/aisleTypes/circleAisle.tsx | 14 +- .../instance/aisleTypes/dashedAisle.tsx | 14 +- .../instance/aisleTypes/dottedAisle.tsx | 14 +- .../instance/aisleTypes/junctionAisle.tsx | 14 +- .../instance/aisleTypes/solidAisle.tsx | 15 +- .../scene/postProcessing/postProcessing.tsx | 2 +- app/src/store/builder/useAisleStore.ts | 149 +++-- app/src/store/builder/useBuilderStore.ts | 6 +- 14 files changed, 765 insertions(+), 105 deletions(-) create mode 100644 app/src/components/layout/sidebarRight/properties/SelectedAisleProperties.tsx diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index ae9c908..5e283c9 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -6,7 +6,7 @@ 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 useVersionHistoryVisibleStore, { 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"; @@ -19,8 +19,9 @@ import WallProperties from "./properties/WallProperties"; import FloorProperties from "./properties/FloorProperties"; import SelectedWallProperties from "./properties/SelectedWallProperties"; import SelectedFloorProperties from "./properties/SelectedFloorProperties"; -import ResourceManagement from "./resourceManagement/ResourceManagement"; import SelectedDecalProperties from "./properties/SelectedDecalProperties"; +import SelectedAisleProperties from "./properties/SelectedAisleProperties"; +import ResourceManagement from "./resourceManagement/ResourceManagement"; type DisplayComponent = | "versionHistory" @@ -31,12 +32,13 @@ type DisplayComponent = | "assetProperties" | "selectedWallProperties" | "selectedFloorProperties" + | "selectedDecalProperties" + | "selectedAisleProperties" | "zoneProperties" | "simulations" | "mechanics" | "analysis" | "visualization" - | "selectedDecalProperties" | "resourceManagement" | "none"; @@ -110,23 +112,27 @@ const SideBarRight: React.FC = () => { setDisplayComponent("assetProperties"); return; } - if (!selectedFloorItem && !selectedFloor && !selectedAisle && selectedWall) { + if (!selectedFloorItem && !selectedFloor && !selectedAisle && !selectedDecal && selectedWall) { setDisplayComponent("selectedWallProperties"); return; } - if (!selectedFloorItem && !selectedWall && !selectedAisle && selectedFloor) { + if (!selectedFloorItem && !selectedWall && !selectedAisle && !selectedDecal && selectedFloor) { setDisplayComponent("selectedFloorProperties"); return; } - if (viewVersionHistory) { + if (viewVersionHistory && !selectedFloorItem && !selectedWall && !selectedAisle && !selectedFloor && !selectedDecal) { setDisplayComponent("versionHistory"); return; } - if (selectedDecal) { + if (!selectedFloorItem && !selectedFloor && !selectedAisle && !selectedWall && selectedDecal) { setDisplayComponent("selectedDecalProperties"); return; } - if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal) { + if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal && selectedAisle) { + setDisplayComponent("selectedAisleProperties"); + return; + } + if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle) { if (toolMode === "Aisle") { setDisplayComponent("aisleProperties"); return; @@ -166,12 +172,16 @@ const SideBarRight: React.FC = () => { return ; case "assetProperties": return ; + case "zoneProperties": + return ; case "selectedWallProperties": return ; case "selectedFloorProperties": return ; - case "zoneProperties": - return ; + case "selectedDecalProperties": + return ; + case "selectedAisleProperties": + return ; case "simulations": return ; case "mechanics": @@ -180,8 +190,6 @@ const SideBarRight: React.FC = () => { return ; case "visualization": return ; - case "selectedDecalProperties": - return ; case "resourceManagement": return ; default: diff --git a/app/src/components/layout/sidebarRight/properties/SelectedAisleProperties.tsx b/app/src/components/layout/sidebarRight/properties/SelectedAisleProperties.tsx new file mode 100644 index 0000000..c1e1d24 --- /dev/null +++ b/app/src/components/layout/sidebarRight/properties/SelectedAisleProperties.tsx @@ -0,0 +1,545 @@ +import React, { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; +import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; +import { ArrowIcon } from "../../../icons/ExportCommonIcons"; + +// image imports +import Arc from "../../../../assets/image/aisleTypes/Arc.png"; +import Arrow from "../../../../assets/image/aisleTypes/Arrow.png"; +import Arrows from "../../../../assets/image/aisleTypes/Arrows.png"; +import Circle from "../../../../assets/image/aisleTypes/Circle.png"; +import Dashed from "../../../../assets/image/aisleTypes/Dashed.png"; +import Directional from "../../../../assets/image/aisleTypes/Directional.png"; +import Dotted from "../../../../assets/image/aisleTypes/Dotted.png"; +import Solid from "../../../../assets/image/aisleTypes/Solid.png"; +import InputToggle from "../../../ui/inputs/InputToggle"; +import { useBuilderStore } from "../../../../store/builder/useBuilderStore"; +import { useSceneContext } from "../../../../modules/scene/sceneContext"; +import { useVersionContext } from "../../../../modules/builder/version/versionContext"; +import { useSocketStore } from "../../../../store/builder/store"; +import { getUserData } from "../../../../functions/getUserData"; + +// import { upsertAisleApi } from "../../../../services/factoryBuilder/aisle/upsertAisleApi"; + +interface TextureItem { + color: string; + id: AisleColors; + brief: string; + texture: string; +} + +const SelectedAisleProperties: React.FC = () => { + const [collapsePresets, setCollapsePresets] = useState(false); + const [collapseTexture, setCollapseTexture] = useState(true); + const { aisleStore } = useSceneContext(); + const { getAisleById, updateAisle, setDashedAisleProperties, setDottedAisleProperties, setArrowsAisleProperties, setArcAisleWidth, setColor } = aisleStore(); + const { selectedVersionStore } = useVersionContext(); + const { selectedVersion } = selectedVersionStore(); + const { socket } = useSocketStore(); + const { userId, organization } = getUserData(); + const { projectId } = useParams(); + const [selectedAisleData, setSelectedAisleData] = useState(); + + const { selectedAisle, setSelectedAisle } = useBuilderStore(); + + useEffect(() => { + const aisleData = getAisleById(selectedAisle?.aisleMesh?.uuid || ""); + setSelectedAisleData(aisleData); + }, [selectedAisle, getAisleById]); + + if (!selectedAisleData) return null; + + const updateBackend = (updatedAisle: Aisle) => { + if (updatedAisle && projectId) { + + // API + + // upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || ''); + + // SOCKET + + const data = { + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization, + aisleUuid: updatedAisle.aisleUuid, + points: updatedAisle.points, + type: updatedAisle.type + } + + socket.emit('v1:model-aisle:add', data); + } + } + + const aisleTextureList: TextureItem[] = [ + { color: "yellow", id: "yellow", brief: "pedestrian walkways", texture: "" }, + { color: "gray", id: "gray", brief: "basic", texture: "" }, + { color: "green", id: "green", brief: "pedestrian walkways", texture: "" }, + { color: "orange", id: "orange", brief: "material flow", texture: "" }, + { color: "blue", id: "blue", brief: "vehicle paths", texture: "" }, + { color: "purple", id: "purple", brief: "material flow", texture: "" }, + { color: "red", id: "red", brief: "safety zone", texture: "" }, + { color: "bright green", id: "#66FF00", brief: "safety zone", texture: "" }, + { color: "yellow-black", id: "yellow-black", brief: "utility aisles", texture: "" }, + { color: "white-black", id: "white-black", brief: "utility aisles", texture: "" }, + ]; + + const aisleTypes: { + name: string; + type: AisleTypes; + id: string; + thumbnail: string; + }[] = [ + { name: "Solid", type: "solid-aisle", id: "1", thumbnail: Solid }, + { name: "Dotted", type: "dotted-aisle", id: "2", thumbnail: Dotted }, + { name: "Dashed", type: "dashed-aisle", id: "3", thumbnail: Dashed }, + { name: "Arrow", type: "arrow-aisle", id: "4", thumbnail: Arrow }, + { name: "Continuous Arrows", type: "arrows-aisle", id: "5", thumbnail: Arrows }, + { name: "Directional", type: "junction-aisle", id: "6", thumbnail: Directional }, + { name: "Arc", type: "arc-aisle", id: "7", thumbnail: Arc }, + { name: "Circle", type: "circle-aisle", id: "8", thumbnail: Circle }, + ]; + + const createAisleTypeObject = (newType: AisleTypes, currentType: AisleType): AisleType => { + switch (newType) { + case 'solid-aisle': + return { + aisleType: 'solid-aisle', + aisleColor: currentType.aisleColor, + aisleWidth: 'aisleWidth' in currentType ? currentType.aisleWidth : 0.1 + } as SolidAisle; + + case 'dashed-aisle': + return { + aisleType: 'dashed-aisle', + aisleColor: currentType.aisleColor, + aisleWidth: 'aisleWidth' in currentType ? currentType.aisleWidth : 0.1, + dashLength: 'dashLength' in currentType ? (currentType as DashedAisle).dashLength : 0.5, + gapLength: 'gapLength' in currentType ? (currentType as DashedAisle).gapLength : 0.3 + } as DashedAisle; + + case 'dotted-aisle': + return { + aisleType: 'dotted-aisle', + aisleColor: currentType.aisleColor, + dotRadius: 'dotRadius' in currentType ? (currentType as DottedAisle).dotRadius : 0.1, + gapLength: 'gapLength' in currentType ? (currentType as DottedAisle).gapLength : 0.3 + } as DottedAisle; + + case 'arrow-aisle': + return { + aisleType: 'arrow-aisle', + aisleColor: currentType.aisleColor, + aisleWidth: 'aisleWidth' in currentType ? currentType.aisleWidth : 0.1 + } as ArrowAisle; + + case 'arrows-aisle': + return { + aisleType: 'arrows-aisle', + aisleColor: currentType.aisleColor, + aisleWidth: 'aisleWidth' in currentType ? currentType.aisleWidth : 0.1, + aisleLength: 'aisleLength' in currentType ? (currentType as ArrowsAisle).aisleLength : 0.6, + gapLength: 'gapLength' in currentType ? (currentType as ArrowsAisle).gapLength : 0.3 + } as ArrowsAisle; + + case 'arc-aisle': + return { + aisleType: 'arc-aisle', + aisleColor: currentType.aisleColor, + aisleWidth: 'aisleWidth' in currentType ? currentType.aisleWidth : 0.1, + isFlipped: 'isFlipped' in currentType ? (currentType as ArcAisle).isFlipped : false + } as ArcAisle; + + case 'circle-aisle': + return { + aisleType: 'circle-aisle', + aisleColor: currentType.aisleColor, + aisleWidth: 'aisleWidth' in currentType ? currentType.aisleWidth : 0.1 + } as CircleAisle; + + case 'junction-aisle': + return { + aisleType: 'junction-aisle', + aisleColor: currentType.aisleColor, + aisleWidth: 'aisleWidth' in currentType ? currentType.aisleWidth : 0.1, + isFlipped: 'isFlipped' in currentType ? (currentType as JunctionAisle).isFlipped : false + } as JunctionAisle; + + default: + return { + aisleType: 'solid-aisle', + aisleColor: currentType.aisleColor, + aisleWidth: 0.1 + } as SolidAisle; + } + }; + + const handleAisleTypeChange = (newType: AisleTypes) => { + if (!selectedAisle?.aisleData) return; + const newAisleType = createAisleTypeObject(newType, selectedAisleData.type); + + const updatedAisle = updateAisle(selectedAisleData.aisleUuid, { + type: newAisleType + }); + + setSelectedAisle({ aisleData: selectedAisle.aisleData, aisleMesh: null }); + + setSelectedAisleData({ + ...selectedAisleData, + type: newAisleType + }); + + if (updatedAisle) { + updateBackend(updatedAisle); + } + }; + + const handleColorChange = (value: AisleColors) => { + const updatedAisle = setColor(selectedAisleData.aisleUuid, value); + + setSelectedAisleData({ + ...selectedAisleData, + type: { + ...selectedAisleData.type, + aisleColor: value + } + }) + + if (updatedAisle) { + updateBackend(updatedAisle); + } + }; + + const handleAisleWidthChange = (value: string) => { + const width = parseFloat(value); + if (!isNaN(width) && selectedAisleData.type.aisleType !== 'dotted-aisle') { + const updatedAisle = updateAisle(selectedAisleData.aisleUuid, { + type: { + ...selectedAisleData.type, + aisleWidth: width + } + }); + + setSelectedAisleData({ + ...selectedAisleData, + type: { + ...selectedAisleData.type, + aisleWidth: width + } + }) + + if (updatedAisle) { + updateBackend(updatedAisle); + } + } + }; + + const handleDashLengthChange = (value: string) => { + const length = parseFloat(value); + if (!isNaN(length) && selectedAisleData.type.aisleType === 'dashed-aisle') { + const updatedAisle = setDashedAisleProperties(selectedAisleData.aisleUuid, { + dashLength: length + }); + + setSelectedAisleData({ + ...selectedAisleData, + type: { + ...(selectedAisleData.type as DashedAisle), + dashLength: length + } + }) + + if (updatedAisle) { + updateBackend(updatedAisle); + } + } + }; + + const handleGapLengthChange = (value: string) => { + const length = parseFloat(value); + if (!isNaN(length) && (selectedAisleData.type.aisleType === 'dashed-aisle' || selectedAisleData.type.aisleType === 'dotted-aisle' || selectedAisleData.type.aisleType === 'arrows-aisle')) { + if (selectedAisleData.type.aisleType === 'dashed-aisle') { + const updatedAisle = setDashedAisleProperties(selectedAisleData.aisleUuid, { + gapLength: length + }); + + setSelectedAisleData({ + ...selectedAisleData, + type: { + ...(selectedAisleData.type as DashedAisle), + gapLength: length + } + }) + + if (updatedAisle) { + updateBackend(updatedAisle); + } + } else if (selectedAisleData.type.aisleType === 'dotted-aisle') { + const updatedAisle = setDottedAisleProperties(selectedAisleData.aisleUuid, { + gapLength: length + }); + + setSelectedAisleData({ + ...selectedAisleData, + type: { + ...(selectedAisleData.type as DottedAisle), + gapLength: length + } + }) + + if (updatedAisle) { + updateBackend(updatedAisle); + } + } else if (selectedAisleData.type.aisleType === 'arrows-aisle') { + const updatedAisle = setArrowsAisleProperties(selectedAisleData.aisleUuid, { + gapLength: length + }); + + setSelectedAisleData({ + ...selectedAisleData, + type: { + ...(selectedAisleData.type as ArrowsAisle), + gapLength: length + } + }) + + if (updatedAisle) { + updateBackend(updatedAisle); + } + } + } + }; + + const handleDotRadiusChange = (value: string) => { + const radius = parseFloat(value); + if (!isNaN(radius) && selectedAisleData.type.aisleType === 'dotted-aisle') { + const updatedAisle = setDottedAisleProperties(selectedAisleData.aisleUuid, { + dotRadius: radius + }); + + setSelectedAisleData({ + ...selectedAisleData, + type: { + ...(selectedAisleData.type as DottedAisle), + dotRadius: radius + } + }) + + if (updatedAisle) { + updateBackend(updatedAisle); + } + } + }; + + const handleAisleLengthChange = (value: string) => { + const length = parseFloat(value); + if (!isNaN(length) && selectedAisleData.type.aisleType === 'arrows-aisle') { + const updatedAisle = setArrowsAisleProperties(selectedAisleData.aisleUuid, { + aisleLength: length + }); + + setSelectedAisleData({ + ...selectedAisleData, + type: { + ...(selectedAisleData.type as ArrowsAisle), + aisleLength: length + } + }) + + if (updatedAisle) { + updateBackend(updatedAisle); + } + } + }; + + const handleIsFlippedChange = () => { + if (selectedAisleData.type.aisleType === 'arc-aisle' || selectedAisleData.type.aisleType === 'junction-aisle') { + const currentType = selectedAisleData.type as ArcAisle | JunctionAisle; + const currentFlipped = currentType.isFlipped || false; + const updatedAisle = setArcAisleWidth(selectedAisleData.aisleUuid, { + isFlipped: !currentFlipped + }); + + setSelectedAisleData({ + ...selectedAisleData, + type: { + ...currentType, + isFlipped: !currentFlipped + } + }) + + if (updatedAisle) { + updateBackend(updatedAisle); + } + } + }; + + const renderAdvancedProperties = () => { + switch (selectedAisleData.type.aisleType) { + case 'dashed-aisle': + const dashedType = selectedAisleData.type as DashedAisle; + return ( + <> + + + + ); + case 'dotted-aisle': + const dottedType = selectedAisleData.type as DottedAisle; + return ( + <> + + + + ); + case 'arrows-aisle': + const arrowsType = selectedAisleData.type as ArrowsAisle; + return ( + <> + + + + ); + case 'junction-aisle': + case 'arc-aisle': + const flippedType = selectedAisleData.type as ArcAisle | JunctionAisle; + return ( + + ); + default: + return null; + } + }; + + return ( +
+
Properties
+ + {/* Basic Properties */} +
+ {selectedAisleData.type.aisleType !== 'dotted-aisle' && + + } + {renderAdvancedProperties()} +
+ + {/* Presets */} +
+ + {!collapsePresets && ( +
+ {aisleTypes.map((val) => ( +
+ +
+ ))} +
+ )} +
+ + {/* Texture */} +
+ + + {collapseTexture && ( +
+ {aisleTextureList.map((val) => ( + + ))} +
+ )} +
+
+ ); +}; + +export default SelectedAisleProperties; \ No newline at end of file diff --git a/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx b/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx index 99c16da..e605363 100644 --- a/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/SelectedDecalProperties.tsx @@ -5,7 +5,6 @@ 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"; @@ -134,18 +133,22 @@ const SelectedDecalProperties = () => {
Decal Properties
- { handleRotationChange(parseFloat(e)) }} + handleRotationChange(value)} /> - { handleScaleChange(parseFloat(e)) }} + + handleScaleChange(value)} />
diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arcAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arcAisle.tsx index bc09b68..d791f8f 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arcAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arcAisle.tsx @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { Extrude } from '@react-three/drei'; import * as Constants from '../../../../../../types/world/worldConstants'; import { useToolMode } from '../../../../../../store/builder/store'; @@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore function ArcAisle({ aisle }: { readonly aisle: Aisle }) { const aisleRef = useRef(null); const { toolMode } = useToolMode(); - const { setSelectedAisle, hoveredPoint } = useBuilderStore(); + const { setSelectedAisle, hoveredPoint, selectedAisle } = useBuilderStore(); + + useEffect(() => { + if (selectedAisle?.aisleData.aisleUuid === aisle.aisleUuid && !selectedAisle.aisleMesh) { + setSelectedAisle({ aisleData: selectedAisle.aisleData, aisleMesh: aisleRef.current }); + } + }, [selectedAisle]) const arc = useMemo(() => { if (aisle.points.length < 2 || aisle.type.aisleType !== 'arc-aisle') return null; @@ -63,8 +69,8 @@ function ArcAisle({ aisle }: { readonly aisle: Aisle }) { }, [aisle]); const handleClick = () => { - if (toolMode === 'move' && !hoveredPoint) { - setSelectedAisle(aisleRef.current); + if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) { + setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle }); } } diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowAisle.tsx index 49bf666..115edc6 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowAisle.tsx @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { Extrude } from '@react-three/drei'; import * as Constants from '../../../../../../types/world/worldConstants'; import { useToolMode } from '../../../../../../store/builder/store'; @@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore function ArrowAisle({ aisle }: { readonly aisle: Aisle }) { const aisleRef = useRef(null); const { toolMode } = useToolMode(); - const { setSelectedAisle, hoveredPoint } = useBuilderStore(); + const { setSelectedAisle, hoveredPoint, selectedAisle } = useBuilderStore(); + + useEffect(() => { + if (selectedAisle?.aisleData.aisleUuid === aisle.aisleUuid && !selectedAisle.aisleMesh) { + setSelectedAisle({ aisleData: selectedAisle.aisleData, aisleMesh: aisleRef.current }); + } + }, [selectedAisle]) const arrow = useMemo(() => { if (aisle.points.length < 2 || aisle.type.aisleType !== 'arrow-aisle') return null; @@ -50,8 +56,8 @@ function ArrowAisle({ aisle }: { readonly aisle: Aisle }) { }, [aisle]); const handleClick = () => { - if (toolMode === 'move' && !hoveredPoint) { - setSelectedAisle(aisleRef.current); + if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) { + setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle }); } } diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx index 6908cf3..3700d55 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { Instances, Instance } from '@react-three/drei'; import * as Constants from '../../../../../../types/world/worldConstants'; import { useToolMode } from '../../../../../../store/builder/store'; @@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) { const aisleRef = useRef(null); const { toolMode } = useToolMode(); - const { setSelectedAisle, hoveredPoint } = useBuilderStore(); + const { setSelectedAisle, hoveredPoint, selectedAisle } = useBuilderStore(); + + useEffect(() => { + if (selectedAisle?.aisleData.aisleUuid === aisle.aisleUuid && !selectedAisle.aisleMesh) { + setSelectedAisle({ aisleData: selectedAisle.aisleData, aisleMesh: aisleRef.current }); + } + }, [selectedAisle]) const { arrowGeometry, arrowInstances } = useMemo(() => { const result = { @@ -68,8 +74,8 @@ function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) { }, [aisle]); const handleClick = () => { - if (toolMode === 'move' && !hoveredPoint) { - setSelectedAisle(aisleRef.current); + if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) { + setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle }); } }; diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/circleAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/circleAisle.tsx index af852e8..d9bc2d2 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/circleAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/circleAisle.tsx @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { Extrude } from '@react-three/drei'; import * as Constants from '../../../../../../types/world/worldConstants'; import { useToolMode } from '../../../../../../store/builder/store'; @@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore function CircleAisle({ aisle }: { readonly aisle: Aisle }) { const aisleRef = useRef(null); const { toolMode } = useToolMode(); - const { setSelectedAisle, hoveredPoint } = useBuilderStore(); + const { setSelectedAisle, hoveredPoint, selectedAisle } = useBuilderStore(); + + useEffect(() => { + if (selectedAisle?.aisleData.aisleUuid === aisle.aisleUuid && !selectedAisle.aisleMesh) { + setSelectedAisle({ aisleData: selectedAisle.aisleData, aisleMesh: aisleRef.current }); + } + }, [selectedAisle]) const circle = useMemo(() => { if (aisle.points.length < 2 || aisle.type.aisleType !== 'circle-aisle') return null; @@ -38,8 +44,8 @@ function CircleAisle({ aisle }: { readonly aisle: Aisle }) { }, [aisle]); const handleClick = () => { - if (toolMode === 'move' && !hoveredPoint) { - setSelectedAisle(aisleRef.current); + if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) { + setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle }); } } diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx index 72fb3c7..b00c87b 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { Instances, Instance } from '@react-three/drei'; import * as Constants from '../../../../../../types/world/worldConstants'; import { useToolMode } from '../../../../../../store/builder/store'; @@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore function DashedAisle({ aisle }: { readonly aisle: Aisle }) { const aisleRef = useRef(null); const { toolMode } = useToolMode(); - const { setSelectedAisle, hoveredPoint } = useBuilderStore(); + const { setSelectedAisle, hoveredPoint, selectedAisle } = useBuilderStore(); + + useEffect(() => { + if (selectedAisle?.aisleData.aisleUuid === aisle.aisleUuid && !selectedAisle.aisleMesh) { + setSelectedAisle({ aisleData: selectedAisle.aisleData, aisleMesh: aisleRef.current }); + } + }, [selectedAisle]) const dashInstances = useMemo(() => { if (aisle.points.length < 2 || aisle.type.aisleType !== 'dashed-aisle') return []; @@ -43,8 +49,8 @@ function DashedAisle({ aisle }: { readonly aisle: Aisle }) { }, [aisle]); const handleClick = () => { - if (toolMode === 'move' && !hoveredPoint) { - setSelectedAisle(aisleRef.current); + if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) { + setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle }); } }; diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx index e2b264a..09557aa 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { Instance, Instances } from '@react-three/drei'; import * as Constants from '../../../../../../types/world/worldConstants'; import { useToolMode } from '../../../../../../store/builder/store'; @@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore function DottedAisle({ aisle }: { readonly aisle: Aisle }) { const aisleRef = useRef(null); const { toolMode } = useToolMode(); - const { setSelectedAisle, hoveredPoint } = useBuilderStore(); + const { setSelectedAisle, hoveredPoint, selectedAisle } = useBuilderStore(); + + useEffect(() => { + if (selectedAisle?.aisleData.aisleUuid === aisle.aisleUuid && !selectedAisle.aisleMesh) { + setSelectedAisle({ aisleData: selectedAisle.aisleData, aisleMesh: aisleRef.current }); + } + }, [selectedAisle]) const dotPositions = useMemo(() => { if (aisle.points.length < 2 || aisle.type.aisleType !== 'dotted-aisle') return []; @@ -27,8 +33,8 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) { }, [aisle]); const handleClick = () => { - if (toolMode === 'move' && !hoveredPoint) { - setSelectedAisle(aisleRef.current); + if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) { + setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle }); } } diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/junctionAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/junctionAisle.tsx index a3f8bdf..8d45763 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/junctionAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/junctionAisle.tsx @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { Extrude } from '@react-three/drei'; import * as Constants from '../../../../../../types/world/worldConstants'; import { useToolMode } from '../../../../../../store/builder/store'; @@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore function JunctionAisle({ aisle }: { readonly aisle: Aisle }) { const aisleRef = useRef(null); const { toolMode } = useToolMode(); - const { setSelectedAisle, hoveredPoint } = useBuilderStore(); + const { setSelectedAisle, hoveredPoint, selectedAisle } = useBuilderStore(); + + useEffect(() => { + if (selectedAisle?.aisleData.aisleUuid === aisle.aisleUuid && !selectedAisle.aisleMesh) { + setSelectedAisle({ aisleData: selectedAisle.aisleData, aisleMesh: aisleRef.current }); + } + }, [selectedAisle]) const arrows = useMemo(() => { if (aisle.points.length < 2 || aisle.type.aisleType !== 'junction-aisle') return null; @@ -85,8 +91,8 @@ function JunctionAisle({ aisle }: { readonly aisle: Aisle }) { }, [aisle]); const handleClick = () => { - if (toolMode === 'move' && !hoveredPoint) { - setSelectedAisle(aisleRef.current); + if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) { + setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle }); } } diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/solidAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/solidAisle.tsx index e9321b0..e43f717 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/solidAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/solidAisle.tsx @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { Extrude } from '@react-three/drei'; import * as Constants from '../../../../../../types/world/worldConstants'; import { useToolMode } from '../../../../../../store/builder/store'; @@ -8,7 +8,14 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore function SolidAisle({ aisle }: { readonly aisle: Aisle }) { const aisleRef = useRef(null); const { toolMode } = useToolMode(); - const { setSelectedAisle, hoveredPoint } = useBuilderStore(); + const { setSelectedAisle, hoveredPoint, selectedAisle } = useBuilderStore(); + + useEffect(() => { + if (selectedAisle?.aisleData.aisleUuid === aisle.aisleUuid && !selectedAisle.aisleMesh) { + setSelectedAisle({ aisleData: selectedAisle.aisleData, aisleMesh: aisleRef.current }); + } + }, [selectedAisle]) + const shape = useMemo(() => { if (aisle.points.length < 2 || aisle.type.aisleType !== 'solid-aisle') return null; @@ -35,8 +42,8 @@ function SolidAisle({ aisle }: { readonly aisle: Aisle }) { }, [aisle]); const handleClick = () => { - if (toolMode === 'move' && !hoveredPoint) { - setSelectedAisle(aisleRef.current); + if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) { + setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle }); } } diff --git a/app/src/modules/scene/postProcessing/postProcessing.tsx b/app/src/modules/scene/postProcessing/postProcessing.tsx index 24f7428..e6d656d 100644 --- a/app/src/modules/scene/postProcessing/postProcessing.tsx +++ b/app/src/modules/scene/postProcessing/postProcessing.tsx @@ -120,7 +120,7 @@ export default function PostProcessing() { )} {selectedAisle && ( void; - addAisle: (aisle: Aisle) => void; - updateAisle: (uuid: string, updated: Partial) => void; - removeAisle: (uuid: string) => void; + setAisles: (aisles: Aisles) => Aisles; + addAisle: (aisle: Aisle) => Aisle; + updateAisle: (uuid: string, updated: Partial) => Aisle | undefined; + removeAisle: (uuid: string) => Aisle | undefined; removePoint: (uuid: string) => Aisles; - clearAisles: () => void; + clearAisles: () => Aisles; setPosition: ( pointUuid: string, position: [number, number, number] ) => Aisle | undefined; - setLayer: (pointUuid: string, layer: number) => void; - setColor: (aisleUuid: string, color: AisleColors) => void; + setLayer: (pointUuid: string, layer: number) => Aisle | undefined; + setColor: (aisleUuid: string, color: AisleColors) => Aisle | undefined; - // Type-specific setters - setSolidAisleWidth: (aisleUuid: string, width: number) => void; + setSolidAisleWidth: (aisleUuid: string, width: number) => Aisle | undefined; setDashedAisleProperties: ( aisleUuid: string, props: { aisleWidth?: number; dashLength?: number; gapLength?: number } - ) => void; + ) => Aisle | undefined; setDottedAisleProperties: ( aisleUuid: string, props: { dotRadius?: number; gapLength?: number } - ) => void; - setArrowAisleWidth: (aisleUuid: string, width: number) => void; + ) => Aisle | undefined; + setArrowAisleWidth: (aisleUuid: string, width: number) => Aisle | undefined; setArrowsAisleProperties: ( aisleUuid: string, props: { aisleWidth?: number; aisleLength?: number; gapLength?: number } - ) => void; + ) => Aisle | undefined; setArcAisleWidth: ( aisleUuid: string, props: { aisleWidth?: number; isFlipped: boolean } - ) => void; - setCircleAisleWidth: (aisleUuid: string, width: number) => void; + ) => Aisle | undefined; + setCircleAisleWidth: (aisleUuid: string, width: number) => Aisle | undefined; setJunctionAisleProperties: ( aisleUuid: string, props: { aisleWidth?: number; isFlipped: boolean } - ) => void; + ) => Aisle | undefined; getAisleById: (uuid: string) => Aisle | undefined; getAislesByPointId: (uuid: string) => Aisle[] | []; @@ -53,28 +52,43 @@ export const createAisleStore = () => { immer((set, get) => ({ aisles: [], - setAisles: (aisles) => + setAisles: (aisles) => { set((state) => { state.aisles = aisles; - }), + }); + return aisles; + }, - addAisle: (aisle) => + addAisle: (aisle) => { set((state) => { state.aisles.push(aisle); - }), + }); + return aisle; + }, - updateAisle: (uuid, updated) => + updateAisle: (uuid, updated) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === uuid); if (aisle) { Object.assign(aisle, updated); + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, - removeAisle: (uuid) => + removeAisle: (uuid) => { + let removedAisle: Aisle | undefined; set((state) => { - state.aisles = state.aisles.filter((a) => a.aisleUuid !== uuid); - }), + const index = state.aisles.findIndex((a) => a.aisleUuid === uuid); + if (index !== -1) { + removedAisle = JSON.parse(JSON.stringify(state.aisles[index])); + state.aisles.splice(index, 1); + } + }); + return removedAisle; + }, removePoint: (uuid) => { const removedAisles: Aisle[] = []; @@ -94,9 +108,11 @@ export const createAisleStore = () => { }, clearAisles: () => { + const clearedAisles = get().aisles; set((state) => { state.aisles = []; - }) + }); + return clearedAisles; }, setPosition: (pointUuid, position) => { @@ -113,34 +129,46 @@ export const createAisleStore = () => { return updatedAisle; }, - setLayer: (pointUuid, layer) => + setLayer: (pointUuid, layer) => { + let updatedAisle: Aisle | undefined; set((state) => { for (const aisle of state.aisles) { const point = aisle.points.find((p) => p.pointUuid === pointUuid); if (point) { point.layer = layer; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } } - }), + }); + return updatedAisle; + }, - setColor: (aisleUuid, color) => + setColor: (aisleUuid, color) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); if (aisle) { aisle.type.aisleColor = color; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, - // Type-specific property setters - setSolidAisleWidth: (aisleUuid, width) => + setSolidAisleWidth: (aisleUuid, width) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); if (aisle && aisle.type.aisleType === "solid-aisle") { aisle.type.aisleWidth = width; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, - setDashedAisleProperties: (aisleUuid, props) => + setDashedAisleProperties: (aisleUuid, props) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); if (aisle && aisle.type.aisleType === "dashed-aisle") { @@ -150,10 +178,14 @@ export const createAisleStore = () => { aisle.type.dashLength = props.dashLength; if (props.gapLength !== undefined) aisle.type.gapLength = props.gapLength; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, - setDottedAisleProperties: (aisleUuid, props) => + setDottedAisleProperties: (aisleUuid, props) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); if (aisle && aisle.type.aisleType === "dotted-aisle") { @@ -161,18 +193,26 @@ export const createAisleStore = () => { aisle.type.dotRadius = props.dotRadius; if (props.gapLength !== undefined) aisle.type.gapLength = props.gapLength; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, - setArrowAisleWidth: (aisleUuid, width) => + setArrowAisleWidth: (aisleUuid, width) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); if (aisle && aisle.type.aisleType === "arrow-aisle") { aisle.type.aisleWidth = width; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, - setArrowsAisleProperties: (aisleUuid, props) => + setArrowsAisleProperties: (aisleUuid, props) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); if (aisle && aisle.type.aisleType === "arrows-aisle") { @@ -182,10 +222,14 @@ export const createAisleStore = () => { aisle.type.aisleLength = props.aisleLength; if (props.gapLength !== undefined) aisle.type.gapLength = props.gapLength; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, - setArcAisleWidth: (aisleUuid, props) => + setArcAisleWidth: (aisleUuid, props) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); if (aisle && aisle.type.aisleType === "arc-aisle") { @@ -193,18 +237,26 @@ export const createAisleStore = () => { aisle.type.aisleWidth = props.aisleWidth; if (props.isFlipped !== undefined) aisle.type.isFlipped = props.isFlipped; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, - setCircleAisleWidth: (aisleUuid, width) => + setCircleAisleWidth: (aisleUuid, width) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); if (aisle && aisle.type.aisleType === "circle-aisle") { aisle.type.aisleWidth = width; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, - setJunctionAisleProperties: (aisleUuid, props) => + setJunctionAisleProperties: (aisleUuid, props) => { + let updatedAisle: Aisle | undefined; set((state) => { const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); if (aisle && aisle.type.aisleType === "junction-aisle") { @@ -212,8 +264,11 @@ export const createAisleStore = () => { aisle.type.aisleWidth = props.aisleWidth; if (props.isFlipped !== undefined) aisle.type.isFlipped = props.isFlipped; + updatedAisle = JSON.parse(JSON.stringify(aisle)); } - }), + }); + return updatedAisle; + }, getAisleById: (uuid) => { return get().aisles.find((a) => a.aisleUuid === uuid); diff --git a/app/src/store/builder/useBuilderStore.ts b/app/src/store/builder/useBuilderStore.ts index 476631d..376689b 100644 --- a/app/src/store/builder/useBuilderStore.ts +++ b/app/src/store/builder/useBuilderStore.ts @@ -47,7 +47,7 @@ interface BuilderState { }, // Aisle General - selectedAisle: Object3D | null; + selectedAisle: {aisleMesh: Object3D | null, aisleData: Aisle} | null; aisleType: AisleTypes; aisleWidth: number; aisleColor: AisleColors; @@ -97,7 +97,7 @@ interface BuilderState { setDecalDragState: (isDragging: boolean, draggingDecalUuid: string | null, dragOffset: Vector3 | null) => void; // Setters - Aisle General - setSelectedAisle: (aisle: Object3D | null) => void; + setSelectedAisle: (aisle: {aisleMesh: Object3D | null, aisleData: Aisle} | null) => void; setAisleType: (type: AisleTypes) => void; setAisleWidth: (width: number) => void; setAisleColor: (color: AisleColors) => void; @@ -325,7 +325,7 @@ export const useBuilderStore = create()( // === Setters: Aisle General === - setSelectedAisle: (aisle: Object3D | null) => { + setSelectedAisle: (aisle: {aisleMesh: Object3D | null, aisleData: Aisle} | null) => { set((state) => { state.selectedAisle = aisle; });