From d30ae344264117d8feffa89de0b3931a668d1810 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Thu, 29 May 2025 14:39:19 +0530 Subject: [PATCH] refactor: Add ArrowsAisle component and update aisle properties for improved functionality --- .../properties/AisleProperties.tsx | 2 +- .../Instances/instance/aisleInstance.tsx | 5 ++ .../instance/aisleTypes/arrowsAisle.tsx | 74 ++++++++++++++++++ .../instance/aisleTypes/dashedAisle.tsx | 2 +- .../instance/aisleTypes/dottedAisle.tsx | 4 +- .../aisle/aisleCreator/referenceAisle.tsx | 78 ++++++++++++++++++- app/src/modules/builder/groups/zoneGroup.tsx | 3 +- app/src/store/builder/useBuilderStore.ts | 2 +- 8 files changed, 159 insertions(+), 11 deletions(-) create mode 100644 app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx diff --git a/app/src/components/layout/sidebarRight/properties/AisleProperties.tsx b/app/src/components/layout/sidebarRight/properties/AisleProperties.tsx index db58c7a..c277812 100644 --- a/app/src/components/layout/sidebarRight/properties/AisleProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/AisleProperties.tsx @@ -26,13 +26,13 @@ const AisleProperties: React.FC = () => { const { aisleType, aisleWidth, aisleColor, setAisleType, setAisleColor, setAisleWidth } = useBuilderStore(); const aisleTextureList: TextureItem[] = [ - { color: "gray", id: "gray", brief: "basic", texture: "" }, { color: "yellow", id: "yellow1", brief: "pedestrian walkways", texture: "", }, + { color: "gray", id: "gray", brief: "basic", texture: "" }, { color: "green", id: "green1", brief: "pedestrian walkways", texture: "" }, { color: "orange", id: "orange", brief: "material flow", texture: "" }, { color: "blue", id: "blue", brief: "vehicle paths", texture: "" }, diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleInstance.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleInstance.tsx index 8ab9c5f..9afd3d6 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleInstance.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleInstance.tsx @@ -1,3 +1,4 @@ +import ArrowsAisle from './aisleTypes/arrowsAisle'; import DashedAisle from './aisleTypes/dashedAisle'; import DottedAisle from './aisleTypes/dottedAisle'; import SolidAisle from './aisleTypes/solidAisle'; @@ -17,6 +18,10 @@ function AisleInstance({ aisle }: { readonly aisle: Aisle }) { {aisle.type.aisleType === 'dotted-aisle' && ( )} + + {aisle.type.aisleType === 'arrows-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 new file mode 100644 index 0000000..a71f836 --- /dev/null +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx @@ -0,0 +1,74 @@ +import * as THREE from 'three'; +import { useMemo } from 'react'; +import { Extrude } from '@react-three/drei'; +import * as Constants from '../../../../../../types/world/worldConstants'; + +function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) { + const arrows = useMemo(() => { + if (aisle.points.length < 2) return []; + + const start = new THREE.Vector3(...aisle.points[0].position); + const end = new THREE.Vector3(...aisle.points[1].position); + const width = aisle.type.aisleWidth || 0.1; + const arrowLength = 0.6; + const spacing = 0.6; + + const direction = new THREE.Vector3().subVectors(end, start); + const length = direction.length(); + direction.normalize(); + + const count = Math.floor((length + spacing) / (arrowLength + spacing)); + + const arrowShapes: { shape: THREE.Shape; position: THREE.Vector3; rotationY: number }[] = []; + + for (let i = 0; i < count; i++) { + const initialOffset = 0.6; + const center = new THREE.Vector3().copy(start).addScaledVector(direction, initialOffset + i * (arrowLength + spacing)); + + const shape = new THREE.Shape(); + const w = width * 0.8; + const h = arrowLength; + + shape.moveTo(0, 0); + shape.lineTo(w, h * 0.6); + shape.lineTo(w * 0.4, h * 0.6); + shape.lineTo(w * 0.4, h); + shape.lineTo(-w * 0.4, h); + shape.lineTo(-w * 0.4, h * 0.6); + shape.lineTo(-w, h * 0.6); + shape.lineTo(0, 0); + + const angle = Math.atan2(direction.x, direction.z) + Math.PI; + + arrowShapes.push({ shape, position: center, rotationY: angle }); + } + + return arrowShapes; + }, [aisle]); + + if (arrows.length === 0) return null; + + return ( + + {arrows.map(({ shape, position, rotationY }, index) => ( + + + + + + ))} + + ); +} + +export default ArrowsAisle; 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 7103479..1f0c0d5 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx @@ -17,7 +17,7 @@ function DashedAisle({ aisle }: { readonly aisle: Aisle }) { const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize(); const totalLength = new THREE.Vector3().subVectors(end, start).length(); - const segmentCount = Math.floor(totalLength / (dashLength + gapLength)); + const segmentCount = Math.floor((totalLength + gapLength) / (dashLength + gapLength)); const shapes = []; const directionNormalized = new THREE.Vector3().subVectors(end, start).normalize(); 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 09a3c65..5cdc1d5 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx @@ -11,10 +11,10 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) { const end = new THREE.Vector3(...aisle.points[1].position); const width = aisle.type.aisleWidth || 0.1; const dotSpacing = 0.5; - const dotRadius = width * 0.4; + const dotRadius = width * 0.6; const totalLength = new THREE.Vector3().subVectors(end, start).length(); - const dotCount = Math.floor(totalLength / dotSpacing); + const dotCount = Math.floor((totalLength + (dotSpacing / 2)) / dotSpacing); const shapes = []; const directionNormalized = new THREE.Vector3().subVectors(end, start).normalize(); diff --git a/app/src/modules/builder/aisle/aisleCreator/referenceAisle.tsx b/app/src/modules/builder/aisle/aisleCreator/referenceAisle.tsx index 74d5e1f..e804d35 100644 --- a/app/src/modules/builder/aisle/aisleCreator/referenceAisle.tsx +++ b/app/src/modules/builder/aisle/aisleCreator/referenceAisle.tsx @@ -68,6 +68,8 @@ function ReferenceAisle({ tempPoints, aisleType, aisleWidth, aisleColor }: Reado return ; case 'dotted-aisle': return ; + case 'arrows-aisle': + return default: return null; } @@ -143,7 +145,7 @@ function DashedAisle({ aisle }: { readonly aisle: Aisle }) { const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize(); const totalLength = new THREE.Vector3().subVectors(end, start).length(); - const segmentCount = Math.floor(totalLength / (dashLength + gapLength)); + const segmentCount = Math.floor((totalLength + gapLength) / (dashLength + gapLength)); const shapes = []; const directionNormalized = new THREE.Vector3().subVectors(end, start).normalize(); @@ -202,10 +204,10 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) { const end = new THREE.Vector3(...aisle.points[1].position); const width = aisle.type.aisleWidth || 0.1; const dotSpacing = 0.5; - const dotRadius = width * 0.4; + const dotRadius = width * 0.6; const totalLength = new THREE.Vector3().subVectors(end, start).length(); - const dotCount = Math.floor(totalLength / dotSpacing); + const dotCount = Math.floor((totalLength + (dotSpacing / 2)) / dotSpacing); const shapes = []; const directionNormalized = new THREE.Vector3().subVectors(end, start).normalize(); @@ -244,4 +246,72 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) { ))} ); -} \ No newline at end of file +} + +function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) { + const arrows = useMemo(() => { + if (aisle.points.length < 2) return []; + + const start = new THREE.Vector3(...aisle.points[0].position); + const end = new THREE.Vector3(...aisle.points[1].position); + const width = aisle.type.aisleWidth || 0.1; + const arrowLength = 0.6; + const spacing = 0.6; + + const direction = new THREE.Vector3().subVectors(end, start); + const length = direction.length(); + direction.normalize(); + + const count = Math.floor((length + spacing) / (arrowLength + spacing)); + + const arrowShapes: { shape: THREE.Shape; position: THREE.Vector3; rotationY: number }[] = []; + + for (let i = 0; i < count; i++) { + const initialOffset = 0.6; + const center = new THREE.Vector3().copy(start).addScaledVector(direction, initialOffset + i * (arrowLength + spacing)); + + const shape = new THREE.Shape(); + const w = width * 0.8; + const h = arrowLength; + + shape.moveTo(0, 0); + shape.lineTo(w, h * 0.6); + shape.lineTo(w * 0.4, h * 0.6); + shape.lineTo(w * 0.4, h); + shape.lineTo(-w * 0.4, h); + shape.lineTo(-w * 0.4, h * 0.6); + shape.lineTo(-w, h * 0.6); + shape.lineTo(0, 0); + + const angle = Math.atan2(direction.x, direction.z) + Math.PI; + + arrowShapes.push({ shape, position: center, rotationY: angle }); + } + + return arrowShapes; + }, [aisle]); + + if (arrows.length === 0) return null; + + return ( + + {arrows.map(({ shape, position, rotationY }, index) => ( + + + + + + ))} + + ); +} diff --git a/app/src/modules/builder/groups/zoneGroup.tsx b/app/src/modules/builder/groups/zoneGroup.tsx index 21ba6cc..5b567af 100644 --- a/app/src/modules/builder/groups/zoneGroup.tsx +++ b/app/src/modules/builder/groups/zoneGroup.tsx @@ -553,7 +553,7 @@ const ZoneGroup: React.FC = () => { const midpoint = new THREE.Vector3( (point1.x + point2.x) / 2, CONSTANTS.zoneConfig.height / 2 + - (zone.layer - 1) * CONSTANTS.zoneConfig.height, + (zone.layer - 1) * CONSTANTS.zoneConfig.height, (point1.z + point2.z) / 2 ); @@ -564,7 +564,6 @@ const ZoneGroup: React.FC = () => { return ( ()( immer((set) => ({ aisleType: 'solid-aisle', aisleWidth: 0.1, - aisleColor: 'gray', + aisleColor: 'yellow', setAisleType: (type) => { set((state) => { state.aisleType = type;