added selectedAisleProperties and its backend updation

This commit is contained in:
2025-08-28 18:00:00 +05:30
parent cb87cd067b
commit 94bec4f2f0
14 changed files with 765 additions and 105 deletions

View File

@@ -6,7 +6,7 @@ import { useToggleStore } from "../../../store/useUIToggleStore";
import Visualization from "./visualization/Visualization"; import Visualization from "./visualization/Visualization";
import Analysis from "./analysis/Analysis"; import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations"; 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 { useSelectedEventData, useSelectedEventSphere, } from "../../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import { useBuilderStore } from "../../../store/builder/useBuilderStore";
import GlobalProperties from "./properties/GlobalProperties"; import GlobalProperties from "./properties/GlobalProperties";
@@ -19,8 +19,9 @@ import WallProperties from "./properties/WallProperties";
import FloorProperties from "./properties/FloorProperties"; import FloorProperties from "./properties/FloorProperties";
import SelectedWallProperties from "./properties/SelectedWallProperties"; import SelectedWallProperties from "./properties/SelectedWallProperties";
import SelectedFloorProperties from "./properties/SelectedFloorProperties"; import SelectedFloorProperties from "./properties/SelectedFloorProperties";
import ResourceManagement from "./resourceManagement/ResourceManagement";
import SelectedDecalProperties from "./properties/SelectedDecalProperties"; import SelectedDecalProperties from "./properties/SelectedDecalProperties";
import SelectedAisleProperties from "./properties/SelectedAisleProperties";
import ResourceManagement from "./resourceManagement/ResourceManagement";
type DisplayComponent = type DisplayComponent =
| "versionHistory" | "versionHistory"
@@ -31,12 +32,13 @@ type DisplayComponent =
| "assetProperties" | "assetProperties"
| "selectedWallProperties" | "selectedWallProperties"
| "selectedFloorProperties" | "selectedFloorProperties"
| "selectedDecalProperties"
| "selectedAisleProperties"
| "zoneProperties" | "zoneProperties"
| "simulations" | "simulations"
| "mechanics" | "mechanics"
| "analysis" | "analysis"
| "visualization" | "visualization"
| "selectedDecalProperties"
| "resourceManagement" | "resourceManagement"
| "none"; | "none";
@@ -110,23 +112,27 @@ const SideBarRight: React.FC = () => {
setDisplayComponent("assetProperties"); setDisplayComponent("assetProperties");
return; return;
} }
if (!selectedFloorItem && !selectedFloor && !selectedAisle && selectedWall) { if (!selectedFloorItem && !selectedFloor && !selectedAisle && !selectedDecal && selectedWall) {
setDisplayComponent("selectedWallProperties"); setDisplayComponent("selectedWallProperties");
return; return;
} }
if (!selectedFloorItem && !selectedWall && !selectedAisle && selectedFloor) { if (!selectedFloorItem && !selectedWall && !selectedAisle && !selectedDecal && selectedFloor) {
setDisplayComponent("selectedFloorProperties"); setDisplayComponent("selectedFloorProperties");
return; return;
} }
if (viewVersionHistory) { if (viewVersionHistory && !selectedFloorItem && !selectedWall && !selectedAisle && !selectedFloor && !selectedDecal) {
setDisplayComponent("versionHistory"); setDisplayComponent("versionHistory");
return; return;
} }
if (selectedDecal) { if (!selectedFloorItem && !selectedFloor && !selectedAisle && !selectedWall && selectedDecal) {
setDisplayComponent("selectedDecalProperties"); setDisplayComponent("selectedDecalProperties");
return; return;
} }
if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal) { if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal && selectedAisle) {
setDisplayComponent("selectedAisleProperties");
return;
}
if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle) {
if (toolMode === "Aisle") { if (toolMode === "Aisle") {
setDisplayComponent("aisleProperties"); setDisplayComponent("aisleProperties");
return; return;
@@ -166,12 +172,16 @@ const SideBarRight: React.FC = () => {
return <FloorProperties />; return <FloorProperties />;
case "assetProperties": case "assetProperties":
return <AssetProperties />; return <AssetProperties />;
case "zoneProperties":
return <ZoneProperties />;
case "selectedWallProperties": case "selectedWallProperties":
return <SelectedWallProperties />; return <SelectedWallProperties />;
case "selectedFloorProperties": case "selectedFloorProperties":
return <SelectedFloorProperties />; return <SelectedFloorProperties />;
case "zoneProperties": case "selectedDecalProperties":
return <ZoneProperties />; return <SelectedDecalProperties />;
case "selectedAisleProperties":
return <SelectedAisleProperties />;
case "simulations": case "simulations":
return <Simulations />; return <Simulations />;
case "mechanics": case "mechanics":
@@ -180,8 +190,6 @@ const SideBarRight: React.FC = () => {
return <Analysis />; return <Analysis />;
case "visualization": case "visualization":
return <Visualization />; return <Visualization />;
case "selectedDecalProperties":
return <SelectedDecalProperties />;
case "resourceManagement": case "resourceManagement":
return <ResourceManagement />; return <ResourceManagement />;
default: default:

View File

@@ -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<Aisle | undefined>();
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 (
<>
<InputWithDropDown
label="Dash Length"
value={`${dashedType.dashLength}`}
min={0.1}
step={0.1}
max={2}
onChange={handleDashLengthChange}
/>
<InputWithDropDown
label="Gap Length"
value={`${dashedType.gapLength}`}
min={0.1}
step={0.1}
max={2}
onChange={handleGapLengthChange}
/>
</>
);
case 'dotted-aisle':
const dottedType = selectedAisleData.type as DottedAisle;
return (
<>
<InputWithDropDown
label="Dot Radius"
value={`${dottedType.dotRadius}`}
min={0.1}
step={0.1}
max={2}
onChange={handleDotRadiusChange}
/>
<InputWithDropDown
label="Gap Length"
value={`${dottedType.gapLength}`}
min={0.1}
step={0.1}
max={2}
onChange={handleGapLengthChange}
/>
</>
);
case 'arrows-aisle':
const arrowsType = selectedAisleData.type as ArrowsAisle;
return (
<>
<InputWithDropDown
label="Arrow Length"
value={`${arrowsType.aisleLength}`}
min={0.1}
step={0.1}
max={2}
onChange={handleAisleLengthChange}
/>
<InputWithDropDown
label="Gap Length"
value={`${arrowsType.gapLength}`}
min={0.1}
step={0.1}
max={2}
onChange={handleGapLengthChange}
/>
</>
);
case 'junction-aisle':
case 'arc-aisle':
const flippedType = selectedAisleData.type as ArcAisle | JunctionAisle;
return (
<InputToggle
inputKey="Flip Aisle"
label="Flip Aisle"
value={flippedType.isFlipped || false}
onClick={handleIsFlippedChange}
/>
);
default:
return null;
}
};
return (
<div className="aisle-properties-container">
<div className="header">Properties</div>
{/* Basic Properties */}
<section>
{selectedAisleData.type.aisleType !== 'dotted-aisle' &&
<InputWithDropDown
label="Aisle Width"
value={`${selectedAisleData.type.aisleWidth || 0.5}`}
min={0.1}
step={0.1}
max={2}
onChange={handleAisleWidthChange}
/>
}
{renderAdvancedProperties()}
</section>
{/* Presets */}
<section>
<button
className="header"
onClick={() => setCollapsePresets(!collapsePresets)}
aria-expanded={!collapsePresets}
>
<div className="value">Presets</div>
<div className="icon">
<ArrowIcon />
</div>
</button>
{!collapsePresets && (
<div className="presets-list-container">
{aisleTypes.map((val) => (
<div className="preset-list" key={val.id}>
<button
className={`thumbnail ${selectedAisleData.type.aisleType === val.type ? "selected" : ""}`}
title={val.name}
onClick={() => handleAisleTypeChange(val.type)}
>
<img src={val.thumbnail} alt="" />
</button>
</div>
))}
</div>
)}
</section>
{/* Texture */}
<section>
<button
className="header"
onClick={() => setCollapseTexture(!collapseTexture)}
aria-expanded={!collapseTexture}
>
<div className="value">Aisle Texture</div>
<div className="icon" style={{ rotate: collapseTexture ? "" : "-90deg" }}>
<ArrowIcon />
</div>
</button>
{collapseTexture && (
<div className="aisle-texture-container">
{aisleTextureList.map((val) => (
<button
key={val.id}
title={val.brief || val.id}
className={`aisle-list ${selectedAisleData.type.aisleColor === val.id ? "selected" : ""}`}
onClick={() => handleColorChange(val.id)}
aria-pressed={selectedAisleData.type.aisleColor === val.id}
>
<div className="texture-display">{val.texture}</div>
<div className="aisle-color">{val.color}</div>
<div className="aisle-brief">{`( ${val.brief} )`}</div>
</button>
))}
</div>
)}
</section>
</div>
);
};
export default SelectedAisleProperties;

View File

@@ -5,7 +5,6 @@ import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { LayeringBottomIcon, LayeringTopIcon } from "../../../icons/ExportCommonIcons"; import { LayeringBottomIcon, LayeringTopIcon } from "../../../icons/ExportCommonIcons";
import { useSocketStore } from "../../../../store/builder/store"; import { useSocketStore } from "../../../../store/builder/store";
import InputRange from "../../../ui/inputs/InputRange"; import InputRange from "../../../ui/inputs/InputRange";
import RotationInput from "../customInput/RotationInput";
import { getUserData } from "../../../../functions/getUserData"; import { getUserData } from "../../../../functions/getUserData";
// import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi"; // import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
@@ -134,18 +133,22 @@ const SelectedDecalProperties = () => {
<div className="decal-transformation-container"> <div className="decal-transformation-container">
<div className="header">Decal Properties</div> <div className="header">Decal Properties</div>
<section> <section>
<RotationInput <InputRange
onChange={(e) => { handleRotationChange(parseFloat(e)) }} label="Rotation"
value={selectedDecal.decalData.decalRotation || 0} value={selectedDecal.decalData.decalRotation || 0}
min={0}
max={360}
step={1}
onChange={(value: number) => handleRotationChange(value)}
/> />
<RotationInput
min={0.1} <InputRange
max={10} label="Scale"
step={0.1}
heading="Scaling"
label="Scale :"
onChange={(e) => { handleScaleChange(parseFloat(e)) }}
value={selectedDecal.decalData.decalScale || 1} value={selectedDecal.decalData.decalScale || 1}
min={0.1}
max={5}
step={0.1}
onChange={(value: number) => handleScaleChange(value)}
/> />
</section> </section>

View File

@@ -1,5 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useMemo, useRef } from 'react'; import { useEffect, useMemo, useRef } from 'react';
import { Extrude } from '@react-three/drei'; import { Extrude } from '@react-three/drei';
import * as Constants from '../../../../../../types/world/worldConstants'; import * as Constants from '../../../../../../types/world/worldConstants';
import { useToolMode } from '../../../../../../store/builder/store'; import { useToolMode } from '../../../../../../store/builder/store';
@@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore
function ArcAisle({ aisle }: { readonly aisle: Aisle }) { function ArcAisle({ aisle }: { readonly aisle: Aisle }) {
const aisleRef = useRef<THREE.Group>(null); const aisleRef = useRef<THREE.Group>(null);
const { toolMode } = useToolMode(); 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(() => { const arc = useMemo(() => {
if (aisle.points.length < 2 || aisle.type.aisleType !== 'arc-aisle') return null; if (aisle.points.length < 2 || aisle.type.aisleType !== 'arc-aisle') return null;
@@ -63,8 +69,8 @@ function ArcAisle({ aisle }: { readonly aisle: Aisle }) {
}, [aisle]); }, [aisle]);
const handleClick = () => { const handleClick = () => {
if (toolMode === 'move' && !hoveredPoint) { if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) {
setSelectedAisle(aisleRef.current); setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle });
} }
} }

View File

@@ -1,5 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useMemo, useRef } from 'react'; import { useEffect, useMemo, useRef } from 'react';
import { Extrude } from '@react-three/drei'; import { Extrude } from '@react-three/drei';
import * as Constants from '../../../../../../types/world/worldConstants'; import * as Constants from '../../../../../../types/world/worldConstants';
import { useToolMode } from '../../../../../../store/builder/store'; import { useToolMode } from '../../../../../../store/builder/store';
@@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore
function ArrowAisle({ aisle }: { readonly aisle: Aisle }) { function ArrowAisle({ aisle }: { readonly aisle: Aisle }) {
const aisleRef = useRef<THREE.Group>(null); const aisleRef = useRef<THREE.Group>(null);
const { toolMode } = useToolMode(); 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(() => { const arrow = useMemo(() => {
if (aisle.points.length < 2 || aisle.type.aisleType !== 'arrow-aisle') return null; if (aisle.points.length < 2 || aisle.type.aisleType !== 'arrow-aisle') return null;
@@ -50,8 +56,8 @@ function ArrowAisle({ aisle }: { readonly aisle: Aisle }) {
}, [aisle]); }, [aisle]);
const handleClick = () => { const handleClick = () => {
if (toolMode === 'move' && !hoveredPoint) { if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) {
setSelectedAisle(aisleRef.current); setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle });
} }
} }

View File

@@ -1,5 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useMemo, useRef } from 'react'; import { useEffect, useMemo, useRef } from 'react';
import { Instances, Instance } from '@react-three/drei'; import { Instances, Instance } from '@react-three/drei';
import * as Constants from '../../../../../../types/world/worldConstants'; import * as Constants from '../../../../../../types/world/worldConstants';
import { useToolMode } from '../../../../../../store/builder/store'; import { useToolMode } from '../../../../../../store/builder/store';
@@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore
function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) { function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
const aisleRef = useRef<THREE.Group>(null); const aisleRef = useRef<THREE.Group>(null);
const { toolMode } = useToolMode(); 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 { arrowGeometry, arrowInstances } = useMemo(() => {
const result = { const result = {
@@ -68,8 +74,8 @@ function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
}, [aisle]); }, [aisle]);
const handleClick = () => { const handleClick = () => {
if (toolMode === 'move' && !hoveredPoint) { if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) {
setSelectedAisle(aisleRef.current); setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle });
} }
}; };

View File

@@ -1,5 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useMemo, useRef } from 'react'; import { useEffect, useMemo, useRef } from 'react';
import { Extrude } from '@react-three/drei'; import { Extrude } from '@react-three/drei';
import * as Constants from '../../../../../../types/world/worldConstants'; import * as Constants from '../../../../../../types/world/worldConstants';
import { useToolMode } from '../../../../../../store/builder/store'; import { useToolMode } from '../../../../../../store/builder/store';
@@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore
function CircleAisle({ aisle }: { readonly aisle: Aisle }) { function CircleAisle({ aisle }: { readonly aisle: Aisle }) {
const aisleRef = useRef<THREE.Group>(null); const aisleRef = useRef<THREE.Group>(null);
const { toolMode } = useToolMode(); 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(() => { const circle = useMemo(() => {
if (aisle.points.length < 2 || aisle.type.aisleType !== 'circle-aisle') return null; if (aisle.points.length < 2 || aisle.type.aisleType !== 'circle-aisle') return null;
@@ -38,8 +44,8 @@ function CircleAisle({ aisle }: { readonly aisle: Aisle }) {
}, [aisle]); }, [aisle]);
const handleClick = () => { const handleClick = () => {
if (toolMode === 'move' && !hoveredPoint) { if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) {
setSelectedAisle(aisleRef.current); setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle });
} }
} }

View File

@@ -1,5 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useMemo, useRef } from 'react'; import { useEffect, useMemo, useRef } from 'react';
import { Instances, Instance } from '@react-three/drei'; import { Instances, Instance } from '@react-three/drei';
import * as Constants from '../../../../../../types/world/worldConstants'; import * as Constants from '../../../../../../types/world/worldConstants';
import { useToolMode } from '../../../../../../store/builder/store'; import { useToolMode } from '../../../../../../store/builder/store';
@@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore
function DashedAisle({ aisle }: { readonly aisle: Aisle }) { function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
const aisleRef = useRef<THREE.Group>(null); const aisleRef = useRef<THREE.Group>(null);
const { toolMode } = useToolMode(); 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(() => { const dashInstances = useMemo(() => {
if (aisle.points.length < 2 || aisle.type.aisleType !== 'dashed-aisle') return []; if (aisle.points.length < 2 || aisle.type.aisleType !== 'dashed-aisle') return [];
@@ -43,8 +49,8 @@ function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
}, [aisle]); }, [aisle]);
const handleClick = () => { const handleClick = () => {
if (toolMode === 'move' && !hoveredPoint) { if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) {
setSelectedAisle(aisleRef.current); setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle });
} }
}; };

View File

@@ -1,5 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useMemo, useRef } from 'react'; import { useEffect, useMemo, useRef } from 'react';
import { Instance, Instances } from '@react-three/drei'; import { Instance, Instances } from '@react-three/drei';
import * as Constants from '../../../../../../types/world/worldConstants'; import * as Constants from '../../../../../../types/world/worldConstants';
import { useToolMode } from '../../../../../../store/builder/store'; import { useToolMode } from '../../../../../../store/builder/store';
@@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore
function DottedAisle({ aisle }: { readonly aisle: Aisle }) { function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
const aisleRef = useRef<THREE.Group>(null); const aisleRef = useRef<THREE.Group>(null);
const { toolMode } = useToolMode(); 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(() => { const dotPositions = useMemo(() => {
if (aisle.points.length < 2 || aisle.type.aisleType !== 'dotted-aisle') return []; if (aisle.points.length < 2 || aisle.type.aisleType !== 'dotted-aisle') return [];
@@ -27,8 +33,8 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
}, [aisle]); }, [aisle]);
const handleClick = () => { const handleClick = () => {
if (toolMode === 'move' && !hoveredPoint) { if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) {
setSelectedAisle(aisleRef.current); setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle });
} }
} }

View File

@@ -1,5 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useMemo, useRef } from 'react'; import { useEffect, useMemo, useRef } from 'react';
import { Extrude } from '@react-three/drei'; import { Extrude } from '@react-three/drei';
import * as Constants from '../../../../../../types/world/worldConstants'; import * as Constants from '../../../../../../types/world/worldConstants';
import { useToolMode } from '../../../../../../store/builder/store'; import { useToolMode } from '../../../../../../store/builder/store';
@@ -8,7 +8,13 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore
function JunctionAisle({ aisle }: { readonly aisle: Aisle }) { function JunctionAisle({ aisle }: { readonly aisle: Aisle }) {
const aisleRef = useRef<THREE.Group>(null); const aisleRef = useRef<THREE.Group>(null);
const { toolMode } = useToolMode(); 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(() => { const arrows = useMemo(() => {
if (aisle.points.length < 2 || aisle.type.aisleType !== 'junction-aisle') return null; if (aisle.points.length < 2 || aisle.type.aisleType !== 'junction-aisle') return null;
@@ -85,8 +91,8 @@ function JunctionAisle({ aisle }: { readonly aisle: Aisle }) {
}, [aisle]); }, [aisle]);
const handleClick = () => { const handleClick = () => {
if (toolMode === 'move' && !hoveredPoint) { if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) {
setSelectedAisle(aisleRef.current); setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle });
} }
} }

View File

@@ -1,5 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useMemo, useRef } from 'react'; import { useEffect, useMemo, useRef } from 'react';
import { Extrude } from '@react-three/drei'; import { Extrude } from '@react-three/drei';
import * as Constants from '../../../../../../types/world/worldConstants'; import * as Constants from '../../../../../../types/world/worldConstants';
import { useToolMode } from '../../../../../../store/builder/store'; import { useToolMode } from '../../../../../../store/builder/store';
@@ -8,7 +8,14 @@ import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore
function SolidAisle({ aisle }: { readonly aisle: Aisle }) { function SolidAisle({ aisle }: { readonly aisle: Aisle }) {
const aisleRef = useRef<THREE.Group>(null); const aisleRef = useRef<THREE.Group>(null);
const { toolMode } = useToolMode(); 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(() => { const shape = useMemo(() => {
if (aisle.points.length < 2 || aisle.type.aisleType !== 'solid-aisle') return null; if (aisle.points.length < 2 || aisle.type.aisleType !== 'solid-aisle') return null;
@@ -35,8 +42,8 @@ function SolidAisle({ aisle }: { readonly aisle: Aisle }) {
}, [aisle]); }, [aisle]);
const handleClick = () => { const handleClick = () => {
if (toolMode === 'move' && !hoveredPoint) { if ((toolMode === 'move' || toolMode === 'cursor') && !hoveredPoint) {
setSelectedAisle(aisleRef.current); setSelectedAisle({ aisleMesh: aisleRef.current, aisleData: aisle });
} }
} }

View File

@@ -120,7 +120,7 @@ export default function PostProcessing() {
)} )}
{selectedAisle && ( {selectedAisle && (
<Outline <Outline
selection={flattenChildren(selectedAisle.children)} selection={flattenChildren(selectedAisle.aisleMesh?.children || [])}
selectionLayer={10} selectionLayer={10}
width={2000} width={2000}
blendFunction={BlendFunction.ALPHA} blendFunction={BlendFunction.ALPHA}

View File

@@ -3,43 +3,42 @@ import { immer } from "zustand/middleware/immer";
interface AisleStore { interface AisleStore {
aisles: Aisles; aisles: Aisles;
setAisles: (aisles: Aisles) => void; setAisles: (aisles: Aisles) => Aisles;
addAisle: (aisle: Aisle) => void; addAisle: (aisle: Aisle) => Aisle;
updateAisle: (uuid: string, updated: Partial<Aisle>) => void; updateAisle: (uuid: string, updated: Partial<Aisle>) => Aisle | undefined;
removeAisle: (uuid: string) => void; removeAisle: (uuid: string) => Aisle | undefined;
removePoint: (uuid: string) => Aisles; removePoint: (uuid: string) => Aisles;
clearAisles: () => void; clearAisles: () => Aisles;
setPosition: ( setPosition: (
pointUuid: string, pointUuid: string,
position: [number, number, number] position: [number, number, number]
) => Aisle | undefined; ) => Aisle | undefined;
setLayer: (pointUuid: string, layer: number) => void; setLayer: (pointUuid: string, layer: number) => Aisle | undefined;
setColor: (aisleUuid: string, color: AisleColors) => void; setColor: (aisleUuid: string, color: AisleColors) => Aisle | undefined;
// Type-specific setters setSolidAisleWidth: (aisleUuid: string, width: number) => Aisle | undefined;
setSolidAisleWidth: (aisleUuid: string, width: number) => void;
setDashedAisleProperties: ( setDashedAisleProperties: (
aisleUuid: string, aisleUuid: string,
props: { aisleWidth?: number; dashLength?: number; gapLength?: number } props: { aisleWidth?: number; dashLength?: number; gapLength?: number }
) => void; ) => Aisle | undefined;
setDottedAisleProperties: ( setDottedAisleProperties: (
aisleUuid: string, aisleUuid: string,
props: { dotRadius?: number; gapLength?: number } props: { dotRadius?: number; gapLength?: number }
) => void; ) => Aisle | undefined;
setArrowAisleWidth: (aisleUuid: string, width: number) => void; setArrowAisleWidth: (aisleUuid: string, width: number) => Aisle | undefined;
setArrowsAisleProperties: ( setArrowsAisleProperties: (
aisleUuid: string, aisleUuid: string,
props: { aisleWidth?: number; aisleLength?: number; gapLength?: number } props: { aisleWidth?: number; aisleLength?: number; gapLength?: number }
) => void; ) => Aisle | undefined;
setArcAisleWidth: ( setArcAisleWidth: (
aisleUuid: string, aisleUuid: string,
props: { aisleWidth?: number; isFlipped: boolean } props: { aisleWidth?: number; isFlipped: boolean }
) => void; ) => Aisle | undefined;
setCircleAisleWidth: (aisleUuid: string, width: number) => void; setCircleAisleWidth: (aisleUuid: string, width: number) => Aisle | undefined;
setJunctionAisleProperties: ( setJunctionAisleProperties: (
aisleUuid: string, aisleUuid: string,
props: { aisleWidth?: number; isFlipped: boolean } props: { aisleWidth?: number; isFlipped: boolean }
) => void; ) => Aisle | undefined;
getAisleById: (uuid: string) => Aisle | undefined; getAisleById: (uuid: string) => Aisle | undefined;
getAislesByPointId: (uuid: string) => Aisle[] | []; getAislesByPointId: (uuid: string) => Aisle[] | [];
@@ -53,28 +52,43 @@ export const createAisleStore = () => {
immer((set, get) => ({ immer((set, get) => ({
aisles: [], aisles: [],
setAisles: (aisles) => setAisles: (aisles) => {
set((state) => { set((state) => {
state.aisles = aisles; state.aisles = aisles;
}), });
return aisles;
},
addAisle: (aisle) => addAisle: (aisle) => {
set((state) => { set((state) => {
state.aisles.push(aisle); state.aisles.push(aisle);
}), });
return aisle;
},
updateAisle: (uuid, updated) => updateAisle: (uuid, updated) => {
let updatedAisle: Aisle | undefined;
set((state) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === uuid); const aisle = state.aisles.find((a) => a.aisleUuid === uuid);
if (aisle) { if (aisle) {
Object.assign(aisle, updated); Object.assign(aisle, updated);
updatedAisle = JSON.parse(JSON.stringify(aisle));
} }
}), });
return updatedAisle;
},
removeAisle: (uuid) => removeAisle: (uuid) => {
let removedAisle: Aisle | undefined;
set((state) => { 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) => { removePoint: (uuid) => {
const removedAisles: Aisle[] = []; const removedAisles: Aisle[] = [];
@@ -94,9 +108,11 @@ export const createAisleStore = () => {
}, },
clearAisles: () => { clearAisles: () => {
const clearedAisles = get().aisles;
set((state) => { set((state) => {
state.aisles = []; state.aisles = [];
}) });
return clearedAisles;
}, },
setPosition: (pointUuid, position) => { setPosition: (pointUuid, position) => {
@@ -113,34 +129,46 @@ export const createAisleStore = () => {
return updatedAisle; return updatedAisle;
}, },
setLayer: (pointUuid, layer) => setLayer: (pointUuid, layer) => {
let updatedAisle: Aisle | undefined;
set((state) => { set((state) => {
for (const aisle of state.aisles) { for (const aisle of state.aisles) {
const point = aisle.points.find((p) => p.pointUuid === pointUuid); const point = aisle.points.find((p) => p.pointUuid === pointUuid);
if (point) { if (point) {
point.layer = layer; point.layer = layer;
updatedAisle = JSON.parse(JSON.stringify(aisle));
} }
} }
}), });
return updatedAisle;
},
setColor: (aisleUuid, color) => setColor: (aisleUuid, color) => {
let updatedAisle: Aisle | undefined;
set((state) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle) { if (aisle) {
aisle.type.aisleColor = color; 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) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "solid-aisle") { if (aisle && aisle.type.aisleType === "solid-aisle") {
aisle.type.aisleWidth = width; aisle.type.aisleWidth = width;
updatedAisle = JSON.parse(JSON.stringify(aisle));
} }
}), });
return updatedAisle;
},
setDashedAisleProperties: (aisleUuid, props) => setDashedAisleProperties: (aisleUuid, props) => {
let updatedAisle: Aisle | undefined;
set((state) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "dashed-aisle") { if (aisle && aisle.type.aisleType === "dashed-aisle") {
@@ -150,10 +178,14 @@ export const createAisleStore = () => {
aisle.type.dashLength = props.dashLength; aisle.type.dashLength = props.dashLength;
if (props.gapLength !== undefined) if (props.gapLength !== undefined)
aisle.type.gapLength = props.gapLength; 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) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "dotted-aisle") { if (aisle && aisle.type.aisleType === "dotted-aisle") {
@@ -161,18 +193,26 @@ export const createAisleStore = () => {
aisle.type.dotRadius = props.dotRadius; aisle.type.dotRadius = props.dotRadius;
if (props.gapLength !== undefined) if (props.gapLength !== undefined)
aisle.type.gapLength = props.gapLength; 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) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "arrow-aisle") { if (aisle && aisle.type.aisleType === "arrow-aisle") {
aisle.type.aisleWidth = width; aisle.type.aisleWidth = width;
updatedAisle = JSON.parse(JSON.stringify(aisle));
} }
}), });
return updatedAisle;
},
setArrowsAisleProperties: (aisleUuid, props) => setArrowsAisleProperties: (aisleUuid, props) => {
let updatedAisle: Aisle | undefined;
set((state) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "arrows-aisle") { if (aisle && aisle.type.aisleType === "arrows-aisle") {
@@ -182,10 +222,14 @@ export const createAisleStore = () => {
aisle.type.aisleLength = props.aisleLength; aisle.type.aisleLength = props.aisleLength;
if (props.gapLength !== undefined) if (props.gapLength !== undefined)
aisle.type.gapLength = props.gapLength; 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) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "arc-aisle") { if (aisle && aisle.type.aisleType === "arc-aisle") {
@@ -193,18 +237,26 @@ export const createAisleStore = () => {
aisle.type.aisleWidth = props.aisleWidth; aisle.type.aisleWidth = props.aisleWidth;
if (props.isFlipped !== undefined) if (props.isFlipped !== undefined)
aisle.type.isFlipped = props.isFlipped; 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) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "circle-aisle") { if (aisle && aisle.type.aisleType === "circle-aisle") {
aisle.type.aisleWidth = width; aisle.type.aisleWidth = width;
updatedAisle = JSON.parse(JSON.stringify(aisle));
} }
}), });
return updatedAisle;
},
setJunctionAisleProperties: (aisleUuid, props) => setJunctionAisleProperties: (aisleUuid, props) => {
let updatedAisle: Aisle | undefined;
set((state) => { set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid); const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "junction-aisle") { if (aisle && aisle.type.aisleType === "junction-aisle") {
@@ -212,8 +264,11 @@ export const createAisleStore = () => {
aisle.type.aisleWidth = props.aisleWidth; aisle.type.aisleWidth = props.aisleWidth;
if (props.isFlipped !== undefined) if (props.isFlipped !== undefined)
aisle.type.isFlipped = props.isFlipped; aisle.type.isFlipped = props.isFlipped;
updatedAisle = JSON.parse(JSON.stringify(aisle));
} }
}), });
return updatedAisle;
},
getAisleById: (uuid) => { getAisleById: (uuid) => {
return get().aisles.find((a) => a.aisleUuid === uuid); return get().aisles.find((a) => a.aisleUuid === uuid);

View File

@@ -47,7 +47,7 @@ interface BuilderState {
}, },
// Aisle General // Aisle General
selectedAisle: Object3D | null; selectedAisle: {aisleMesh: Object3D | null, aisleData: Aisle} | null;
aisleType: AisleTypes; aisleType: AisleTypes;
aisleWidth: number; aisleWidth: number;
aisleColor: AisleColors; aisleColor: AisleColors;
@@ -97,7 +97,7 @@ interface BuilderState {
setDecalDragState: (isDragging: boolean, draggingDecalUuid: string | null, dragOffset: Vector3 | null) => void; setDecalDragState: (isDragging: boolean, draggingDecalUuid: string | null, dragOffset: Vector3 | null) => void;
// Setters - Aisle General // Setters - Aisle General
setSelectedAisle: (aisle: Object3D | null) => void; setSelectedAisle: (aisle: {aisleMesh: Object3D | null, aisleData: Aisle} | null) => void;
setAisleType: (type: AisleTypes) => void; setAisleType: (type: AisleTypes) => void;
setAisleWidth: (width: number) => void; setAisleWidth: (width: number) => void;
setAisleColor: (color: AisleColors) => void; setAisleColor: (color: AisleColors) => void;
@@ -325,7 +325,7 @@ export const useBuilderStore = create<BuilderState>()(
// === Setters: Aisle General === // === Setters: Aisle General ===
setSelectedAisle: (aisle: Object3D | null) => { setSelectedAisle: (aisle: {aisleMesh: Object3D | null, aisleData: Aisle} | null) => {
set((state) => { set((state) => {
state.selectedAisle = aisle; state.selectedAisle = aisle;
}); });