Refactor aisle properties and types in builder store
- Updated AisleProperties component to include new properties for dashed, dotted, and arrows aisles. - Added new handlers for dash length, gap length, dot radius, and aisle length changes. - Enhanced aisle type management in AisleCreator to handle new aisle types and their properties. - Introduced type-specific setters in useAisleStore for better aisle property management. - Updated builderTypes to define specific interfaces for each aisle type. - Improved rendering logic for advanced properties based on selected aisle type.
This commit is contained in:
parent
d30ae34426
commit
9875239d54
|
@ -23,39 +23,20 @@ interface TextureItem {
|
||||||
const AisleProperties: React.FC = () => {
|
const AisleProperties: React.FC = () => {
|
||||||
const [collapsePresets, setCollapsePresets] = useState(false);
|
const [collapsePresets, setCollapsePresets] = useState(false);
|
||||||
const [collapseTexture, setCollapseTexture] = useState(true);
|
const [collapseTexture, setCollapseTexture] = useState(true);
|
||||||
const { aisleType, aisleWidth, aisleColor, setAisleType, setAisleColor, setAisleWidth } = useBuilderStore();
|
|
||||||
|
const { aisleType, aisleWidth, aisleColor, dashLength, gapLength, dotRadius, aisleLength, setAisleType, setAisleColor, setAisleWidth, setDashLength, setGapLength, setDotRadius, setAisleLength } = useBuilderStore();
|
||||||
|
|
||||||
const aisleTextureList: TextureItem[] = [
|
const aisleTextureList: TextureItem[] = [
|
||||||
{
|
{ color: "yellow", id: "yellow1", brief: "pedestrian walkways", texture: "" },
|
||||||
color: "yellow",
|
|
||||||
id: "yellow1",
|
|
||||||
brief: "pedestrian walkways",
|
|
||||||
texture: "",
|
|
||||||
},
|
|
||||||
{ color: "gray", id: "gray", brief: "basic", texture: "" },
|
{ color: "gray", id: "gray", brief: "basic", texture: "" },
|
||||||
{ color: "green", id: "green1", brief: "pedestrian walkways", texture: "" },
|
{ color: "green", id: "green1", brief: "pedestrian walkways", texture: "" },
|
||||||
{ color: "orange", id: "orange", brief: "material flow", texture: "" },
|
{ color: "orange", id: "orange", brief: "material flow", texture: "" },
|
||||||
{ color: "blue", id: "blue", brief: "vehicle paths", texture: "" },
|
{ color: "blue", id: "blue", brief: "vehicle paths", texture: "" },
|
||||||
{ color: "purple", id: "purple", brief: "material flow", texture: "" },
|
{ color: "purple", id: "purple", brief: "material flow", texture: "" },
|
||||||
{ color: "red", id: "red", brief: "safety zone", texture: "" },
|
{ color: "red", id: "red", brief: "safety zone", texture: "" },
|
||||||
{
|
{ color: "bright green", id: "bright-green", brief: "safety zone", texture: "" },
|
||||||
color: "bright green",
|
{ color: "yellow-black", id: "yellow-black", brief: "utility aisles", texture: "" },
|
||||||
id: "bright-green",
|
{ color: "white-black", id: "white-black", brief: "utility aisles", texture: "" },
|
||||||
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: {
|
const aisleTypes: {
|
||||||
|
@ -64,77 +45,148 @@ const AisleProperties: React.FC = () => {
|
||||||
id: string;
|
id: string;
|
||||||
thumbnail: string;
|
thumbnail: string;
|
||||||
}[] = [
|
}[] = [
|
||||||
{
|
{ name: "Solid", type: "solid-aisle", id: "1", thumbnail: Solid },
|
||||||
name: "Solid",
|
{ name: "Dotted", type: "dotted-aisle", id: "2", thumbnail: Dotted },
|
||||||
type: "solid-aisle",
|
{ name: "Dashed", type: "dashed-aisle", id: "3", thumbnail: Dashed },
|
||||||
id: "1",
|
{ name: "Arrow", type: "arrow-aisle", id: "4", thumbnail: Arrow },
|
||||||
thumbnail: Solid,
|
{ 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: "Dotted",
|
{ name: "Circle", type: "circle-aisle", id: "8", thumbnail: Circle },
|
||||||
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: "Contiuous 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 handleAisleWidthChange = (value: string) => {
|
const handleAisleWidthChange = (value: string) => {
|
||||||
const width = parseFloat(value);
|
const width = parseFloat(value);
|
||||||
if (isNaN(width)) {
|
if (!isNaN(width)) {
|
||||||
return;
|
setAisleWidth(width);
|
||||||
}
|
}
|
||||||
setAisleWidth(width);
|
};
|
||||||
}
|
|
||||||
|
const handleDashLengthChange = (value: string) => {
|
||||||
|
const length = parseFloat(value);
|
||||||
|
if (!isNaN(length)) {
|
||||||
|
setDashLength(length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGapLengthChange = (value: string) => {
|
||||||
|
const length = parseFloat(value);
|
||||||
|
if (!isNaN(length)) {
|
||||||
|
setGapLength(length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDotRadiusChange = (value: string) => {
|
||||||
|
const radius = parseFloat(value);
|
||||||
|
if (!isNaN(radius)) {
|
||||||
|
setDotRadius(radius);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAisleLengthChange = (value: string) => {
|
||||||
|
const length = parseFloat(value);
|
||||||
|
if (!isNaN(length)) {
|
||||||
|
setAisleLength(length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderAdvancedProperties = () => {
|
||||||
|
switch (aisleType) {
|
||||||
|
case 'dashed-aisle':
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{aisleType &&
|
||||||
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Dash Length"
|
||||||
|
value={`${dashLength}`}
|
||||||
|
min={0.1}
|
||||||
|
step={0.1}
|
||||||
|
max={2}
|
||||||
|
onChange={handleDashLengthChange}
|
||||||
|
/>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Gap Length"
|
||||||
|
value={`${gapLength}`}
|
||||||
|
min={0.1}
|
||||||
|
step={0.1}
|
||||||
|
max={2}
|
||||||
|
onChange={handleGapLengthChange}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
case 'dotted-aisle':
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{aisleType &&
|
||||||
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Dot Radius"
|
||||||
|
value={`${dotRadius}`}
|
||||||
|
min={0.1}
|
||||||
|
step={0.1}
|
||||||
|
max={2}
|
||||||
|
onChange={handleDotRadiusChange}
|
||||||
|
/>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Gap Length"
|
||||||
|
value={`${gapLength}`}
|
||||||
|
min={0.1}
|
||||||
|
step={0.1}
|
||||||
|
max={2}
|
||||||
|
onChange={handleGapLengthChange}
|
||||||
|
/></>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
case 'arrows-aisle':
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{aisleType &&
|
||||||
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Arrow Length"
|
||||||
|
value={`${aisleLength}`}
|
||||||
|
min={0.1}
|
||||||
|
step={0.1}
|
||||||
|
max={2}
|
||||||
|
onChange={handleAisleLengthChange}
|
||||||
|
/>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Gap Length"
|
||||||
|
value={`${gapLength}`}
|
||||||
|
min={0.1}
|
||||||
|
step={0.1}
|
||||||
|
max={2}
|
||||||
|
onChange={handleGapLengthChange}
|
||||||
|
/></>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="aisle-properties-container">
|
<div className="aisle-properties-container">
|
||||||
<div className="header">Properties</div>
|
<div className="header">Properties</div>
|
||||||
|
|
||||||
|
{/* Basic Properties */}
|
||||||
<section>
|
<section>
|
||||||
<InputWithDropDown
|
{aisleType !== 'dotted-aisle' &&
|
||||||
label="Aisle Width"
|
<InputWithDropDown
|
||||||
value={`${aisleWidth}`}
|
label="Aisle Width"
|
||||||
min={0.1}
|
value={`${aisleWidth}`}
|
||||||
step={0.1}
|
min={0.1}
|
||||||
max={2}
|
step={0.1}
|
||||||
defaultValue="0.1"
|
max={2}
|
||||||
onChange={handleAisleWidthChange}
|
onChange={handleAisleWidthChange}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
|
{renderAdvancedProperties()}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Presets */}
|
{/* Presets */}
|
||||||
|
@ -154,12 +206,9 @@ const AisleProperties: React.FC = () => {
|
||||||
{aisleTypes.map((val) => (
|
{aisleTypes.map((val) => (
|
||||||
<div className="preset-list" key={val.id}>
|
<div className="preset-list" key={val.id}>
|
||||||
<button
|
<button
|
||||||
className={`thumbnail ${aisleType === val.type ? "selected" : ""
|
className={`thumbnail ${aisleType === val.type ? "selected" : ""}`}
|
||||||
}`}
|
|
||||||
title={val.name}
|
title={val.name}
|
||||||
onClick={() => {
|
onClick={() => setAisleType(val.type)}
|
||||||
setAisleType(val.type);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<img src={val.thumbnail} alt="" />
|
<img src={val.thumbnail} alt="" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -177,10 +226,7 @@ const AisleProperties: React.FC = () => {
|
||||||
aria-expanded={!collapseTexture}
|
aria-expanded={!collapseTexture}
|
||||||
>
|
>
|
||||||
<div className="value">Aisle Texture</div>
|
<div className="value">Aisle Texture</div>
|
||||||
<div
|
<div className="icon" style={{ rotate: collapseTexture ? "" : "-90deg" }}>
|
||||||
className="icon"
|
|
||||||
style={{ rotate: collapseTexture ? "" : "-90deg" }}
|
|
||||||
>
|
|
||||||
<ArrowIcon />
|
<ArrowIcon />
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
@ -191,8 +237,7 @@ const AisleProperties: React.FC = () => {
|
||||||
<button
|
<button
|
||||||
key={val.id}
|
key={val.id}
|
||||||
title={val.brief || val.id}
|
title={val.brief || val.id}
|
||||||
className={`aisle-list ${aisleColor === val.color ? "selected" : ""
|
className={`aisle-list ${aisleColor === val.color ? "selected" : ""}`}
|
||||||
}`}
|
|
||||||
onClick={() => setAisleColor(val.color)}
|
onClick={() => setAisleColor(val.color)}
|
||||||
aria-pressed={aisleColor === val.id}
|
aria-pressed={aisleColor === val.id}
|
||||||
>
|
>
|
||||||
|
@ -208,4 +253,4 @@ const AisleProperties: React.FC = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AisleProperties;
|
export default AisleProperties;
|
|
@ -5,13 +5,13 @@ import * as Constants from '../../../../../../types/world/worldConstants';
|
||||||
|
|
||||||
function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
|
function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const arrows = useMemo(() => {
|
const arrows = useMemo(() => {
|
||||||
if (aisle.points.length < 2) return [];
|
if (aisle.points.length < 2 || aisle.type.aisleType !== 'arrows-aisle') return [];
|
||||||
|
|
||||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||||
const width = aisle.type.aisleWidth || 0.1;
|
const width = aisle.type.aisleWidth || 0.1;
|
||||||
const arrowLength = 0.6;
|
const arrowLength = aisle.type.aisleLength || 0.6;
|
||||||
const spacing = 0.6;
|
const spacing = aisle.type.gapLength || 0.6;
|
||||||
|
|
||||||
const direction = new THREE.Vector3().subVectors(end, start);
|
const direction = new THREE.Vector3().subVectors(end, start);
|
||||||
const length = direction.length();
|
const length = direction.length();
|
||||||
|
@ -22,7 +22,7 @@ function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const arrowShapes: { shape: THREE.Shape; position: THREE.Vector3; rotationY: number }[] = [];
|
const arrowShapes: { shape: THREE.Shape; position: THREE.Vector3; rotationY: number }[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const initialOffset = 0.6;
|
const initialOffset = arrowLength;
|
||||||
const center = new THREE.Vector3().copy(start).addScaledVector(direction, initialOffset + i * (arrowLength + spacing));
|
const center = new THREE.Vector3().copy(start).addScaledVector(direction, initialOffset + i * (arrowLength + spacing));
|
||||||
|
|
||||||
const shape = new THREE.Shape();
|
const shape = new THREE.Shape();
|
||||||
|
|
|
@ -5,13 +5,13 @@ import * as Constants from '../../../../../../types/world/worldConstants';
|
||||||
|
|
||||||
function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
|
function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const shapes = useMemo(() => {
|
const shapes = useMemo(() => {
|
||||||
if (aisle.points.length < 2) return [];
|
if (aisle.points.length < 2 || aisle.type.aisleType !== 'dashed-aisle') return [];
|
||||||
|
|
||||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||||
const width = aisle.type.aisleWidth || 0.1;
|
const width = aisle.type.aisleWidth || 0.1;
|
||||||
const dashLength = 0.5;
|
const dashLength = aisle.type.dashLength || 0.5;
|
||||||
const gapLength = 0.3;
|
const gapLength = aisle.type.gapLength || 0.3;
|
||||||
|
|
||||||
const direction = new THREE.Vector3().subVectors(end, start).normalize();
|
const direction = new THREE.Vector3().subVectors(end, start).normalize();
|
||||||
const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize();
|
const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize();
|
||||||
|
|
|
@ -5,12 +5,12 @@ import * as Constants from '../../../../../../types/world/worldConstants';
|
||||||
|
|
||||||
function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
|
function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const shapes = useMemo(() => {
|
const shapes = useMemo(() => {
|
||||||
if (aisle.points.length < 2) return [];
|
if (aisle.points.length < 2 || aisle.type.aisleType !== 'dotted-aisle') return [];
|
||||||
|
|
||||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||||
const width = aisle.type.aisleWidth || 0.1;
|
const width = aisle.type.dotRadius || 0.1;
|
||||||
const dotSpacing = 0.5;
|
const dotSpacing = aisle.type.gapLength || 0.5;
|
||||||
const dotRadius = width * 0.6;
|
const dotRadius = width * 0.6;
|
||||||
|
|
||||||
const totalLength = new THREE.Vector3().subVectors(end, start).length();
|
const totalLength = new THREE.Vector3().subVectors(end, start).length();
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as Constants from '../../../../../../types/world/worldConstants';
|
||||||
|
|
||||||
function SolidAisle({ aisle }: { readonly aisle: Aisle }) {
|
function SolidAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const shape = useMemo(() => {
|
const shape = useMemo(() => {
|
||||||
if (aisle.points.length < 2) return null;
|
if (aisle.points.length < 2 || aisle.type.aisleType !== 'solid-aisle') return null;
|
||||||
|
|
||||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||||
|
|
|
@ -17,7 +17,7 @@ function AisleCreator() {
|
||||||
|
|
||||||
const [tempPoints, setTempPoints] = useState<Point[]>([]);
|
const [tempPoints, setTempPoints] = useState<Point[]>([]);
|
||||||
const [isCreating, setIsCreating] = useState(false);
|
const [isCreating, setIsCreating] = useState(false);
|
||||||
const { aisleType, aisleWidth, aisleColor } = useBuilderStore();
|
const { aisleType, aisleWidth, aisleColor, dashLength, gapLength, dotRadius, aisleLength, } = useBuilderStore();
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// if (tempPoints.length > 0) {
|
// if (tempPoints.length > 0) {
|
||||||
|
@ -86,7 +86,7 @@ function AisleCreator() {
|
||||||
|
|
||||||
if (!point) return;
|
if (!point) return;
|
||||||
|
|
||||||
if (['solid-aisle', 'dashed-aisle', 'stripped-aisle', 'dotted-aisle', 'arrows-aisle'].includes(aisleType)) {
|
if (aisleType === 'solid-aisle') {
|
||||||
const newPoint: Point = {
|
const newPoint: Point = {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
position: [point.x, point.y, point.z],
|
position: [point.x, point.y, point.z],
|
||||||
|
@ -102,18 +102,123 @@ function AisleCreator() {
|
||||||
points: [tempPoints[0], newPoint],
|
points: [tempPoints[0], newPoint],
|
||||||
type: {
|
type: {
|
||||||
typeName: 'Aisle',
|
typeName: 'Aisle',
|
||||||
aisleType: aisleType,
|
aisleType: 'solid-aisle',
|
||||||
aisleColor: aisleColor,
|
aisleColor: aisleColor,
|
||||||
aisleWidth: aisleWidth
|
aisleWidth: aisleWidth
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
addAisle(aisle);
|
addAisle(aisle);
|
||||||
|
|
||||||
setTempPoints([newPoint]);
|
setTempPoints([newPoint]);
|
||||||
}
|
}
|
||||||
} else if (['arc-aisle', 'circle-aisle', 'arrow-aisle', 'junction-aisle'].includes(aisleType)) {
|
} else if (aisleType === 'dashed-aisle') {
|
||||||
console.log();
|
const newPoint: Point = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [point.x, point.y, point.z],
|
||||||
|
layer: activeLayer
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tempPoints.length === 0) {
|
||||||
|
setTempPoints([newPoint]);
|
||||||
|
setIsCreating(true);
|
||||||
|
} else {
|
||||||
|
const aisle: Aisle = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
points: [tempPoints[0], newPoint],
|
||||||
|
type: {
|
||||||
|
typeName: 'Aisle',
|
||||||
|
aisleType: 'dashed-aisle',
|
||||||
|
aisleColor: aisleColor,
|
||||||
|
aisleWidth: aisleWidth,
|
||||||
|
dashLength: dashLength,
|
||||||
|
gapLength: gapLength
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addAisle(aisle);
|
||||||
|
setTempPoints([newPoint]);
|
||||||
|
}
|
||||||
|
} else if (aisleType === 'stripped-aisle') {
|
||||||
|
const newPoint: Point = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [point.x, point.y, point.z],
|
||||||
|
layer: activeLayer
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tempPoints.length === 0) {
|
||||||
|
setTempPoints([newPoint]);
|
||||||
|
setIsCreating(true);
|
||||||
|
} else {
|
||||||
|
const aisle: Aisle = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
points: [tempPoints[0], newPoint],
|
||||||
|
type: {
|
||||||
|
typeName: 'Aisle',
|
||||||
|
aisleType: 'stripped-aisle',
|
||||||
|
aisleColor: aisleColor,
|
||||||
|
aisleWidth: aisleWidth
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addAisle(aisle);
|
||||||
|
setTempPoints([newPoint]);
|
||||||
|
}
|
||||||
|
} else if (aisleType === 'dotted-aisle') {
|
||||||
|
const newPoint: Point = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [point.x, point.y, point.z],
|
||||||
|
layer: activeLayer
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tempPoints.length === 0) {
|
||||||
|
setTempPoints([newPoint]);
|
||||||
|
setIsCreating(true);
|
||||||
|
} else {
|
||||||
|
const aisle: Aisle = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
points: [tempPoints[0], newPoint],
|
||||||
|
type: {
|
||||||
|
typeName: 'Aisle',
|
||||||
|
aisleType: 'dotted-aisle',
|
||||||
|
aisleColor: aisleColor,
|
||||||
|
dotRadius: dotRadius,
|
||||||
|
gapLength: gapLength
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addAisle(aisle);
|
||||||
|
setTempPoints([newPoint]);
|
||||||
|
}
|
||||||
|
} else if (aisleType === 'arrow-aisle') {
|
||||||
|
console.log('Creating arrow-aisle');
|
||||||
|
} else if (aisleType === 'arrows-aisle') {
|
||||||
|
const newPoint: Point = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [point.x, point.y, point.z],
|
||||||
|
layer: activeLayer
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tempPoints.length === 0) {
|
||||||
|
setTempPoints([newPoint]);
|
||||||
|
setIsCreating(true);
|
||||||
|
} else {
|
||||||
|
const aisle: Aisle = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
points: [tempPoints[0], newPoint],
|
||||||
|
type: {
|
||||||
|
typeName: 'Aisle',
|
||||||
|
aisleType: 'arrows-aisle',
|
||||||
|
aisleColor: aisleColor,
|
||||||
|
aisleWidth: aisleWidth,
|
||||||
|
aisleLength: aisleLength,
|
||||||
|
gapLength: gapLength
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addAisle(aisle);
|
||||||
|
setTempPoints([newPoint]);
|
||||||
|
}
|
||||||
|
} else if (aisleType === 'arc-aisle') {
|
||||||
|
console.log('Creating arc-aisle');
|
||||||
|
} else if (aisleType === 'circle-aisle') {
|
||||||
|
console.log('Creating circle-aisle');
|
||||||
|
} else if (aisleType === 'junction-aisle') {
|
||||||
|
console.log('Creating junction-aisle');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -143,7 +248,7 @@ function AisleCreator() {
|
||||||
canvasElement.removeEventListener("click", onMouseClick);
|
canvasElement.removeEventListener("click", onMouseClick);
|
||||||
canvasElement.removeEventListener("contextmenu", onContext);
|
canvasElement.removeEventListener("contextmenu", onContext);
|
||||||
};
|
};
|
||||||
}, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addAisle, aisleType, aisleColor, aisleWidth]);
|
}, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addAisle, aisleType, aisleWidth, aisleColor, dashLength, gapLength, dotRadius, aisleLength]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -161,7 +266,7 @@ function AisleCreator() {
|
||||||
))}
|
))}
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<ReferenceAisle tempPoints={tempPoints} aisleType={aisleType} aisleWidth={aisleWidth} aisleColor={aisleColor} />
|
<ReferenceAisle tempPoints={tempPoints} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,14 @@ import { useFrame, useThree } from '@react-three/fiber';
|
||||||
import { useActiveLayer, useToolMode, useToggleView } from '../../../../store/builder/store';
|
import { useActiveLayer, useToolMode, useToggleView } from '../../../../store/builder/store';
|
||||||
import * as Constants from '../../../../types/world/worldConstants';
|
import * as Constants from '../../../../types/world/worldConstants';
|
||||||
import { Extrude } from '@react-three/drei';
|
import { Extrude } from '@react-three/drei';
|
||||||
|
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
|
||||||
|
|
||||||
interface ReferenceAisleProps {
|
interface ReferenceAisleProps {
|
||||||
tempPoints: Point[];
|
tempPoints: Point[];
|
||||||
aisleType: AisleTypes;
|
|
||||||
aisleWidth: number;
|
|
||||||
aisleColor: AisleColors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReferenceAisle({ tempPoints, aisleType, aisleWidth, aisleColor }: Readonly<ReferenceAisleProps>) {
|
function ReferenceAisle({ tempPoints }: Readonly<ReferenceAisleProps>) {
|
||||||
|
const { aisleType, aisleWidth, aisleColor, dashLength, gapLength, dotRadius, aisleLength, } = useBuilderStore();
|
||||||
const { pointer, raycaster, camera } = useThree();
|
const { pointer, raycaster, camera } = useThree();
|
||||||
const { toolMode } = useToolMode();
|
const { toolMode } = useToolMode();
|
||||||
const { toggleView } = useToggleView();
|
const { toggleView } = useToggleView();
|
||||||
|
@ -31,23 +30,92 @@ function ReferenceAisle({ tempPoints, aisleType, aisleWidth, aisleColor }: Reado
|
||||||
if (intersectionPoint) {
|
if (intersectionPoint) {
|
||||||
mousePosRef.current.copy(intersectionPoint);
|
mousePosRef.current.copy(intersectionPoint);
|
||||||
|
|
||||||
setTempAisle({
|
if (aisleType === 'solid-aisle' || aisleType === 'stripped-aisle') {
|
||||||
uuid: 'temp-aisle',
|
setTempAisle({
|
||||||
points: [
|
uuid: 'temp-aisle',
|
||||||
tempPoints[0],
|
points: [
|
||||||
{
|
tempPoints[0],
|
||||||
uuid: 'temp-point',
|
{
|
||||||
position: [mousePosRef.current.x, mousePosRef.current.y, mousePosRef.current.z],
|
uuid: 'temp-point',
|
||||||
layer: activeLayer
|
position: [mousePosRef.current.x, mousePosRef.current.y, mousePosRef.current.z],
|
||||||
|
layer: activeLayer
|
||||||
|
}
|
||||||
|
],
|
||||||
|
type: {
|
||||||
|
typeName: 'Aisle',
|
||||||
|
aisleType: aisleType,
|
||||||
|
aisleColor: aisleColor,
|
||||||
|
aisleWidth: aisleWidth
|
||||||
}
|
}
|
||||||
],
|
});
|
||||||
type: {
|
} else if (aisleType === 'dashed-aisle') {
|
||||||
typeName: 'Aisle',
|
setTempAisle({
|
||||||
aisleType: aisleType,
|
uuid: 'temp-aisle',
|
||||||
aisleColor: aisleColor,
|
points: [
|
||||||
aisleWidth: aisleWidth
|
tempPoints[0],
|
||||||
}
|
{
|
||||||
});
|
uuid: 'temp-point',
|
||||||
|
position: [mousePosRef.current.x, mousePosRef.current.y, mousePosRef.current.z],
|
||||||
|
layer: activeLayer
|
||||||
|
}
|
||||||
|
],
|
||||||
|
type: {
|
||||||
|
typeName: 'Aisle',
|
||||||
|
aisleType: aisleType,
|
||||||
|
aisleColor: aisleColor,
|
||||||
|
aisleWidth: aisleWidth,
|
||||||
|
dashLength: dashLength,
|
||||||
|
gapLength: gapLength
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (aisleType === 'dotted-aisle') {
|
||||||
|
setTempAisle({
|
||||||
|
uuid: 'temp-aisle',
|
||||||
|
points: [
|
||||||
|
tempPoints[0],
|
||||||
|
{
|
||||||
|
uuid: 'temp-point',
|
||||||
|
position: [mousePosRef.current.x, mousePosRef.current.y, mousePosRef.current.z],
|
||||||
|
layer: activeLayer
|
||||||
|
}
|
||||||
|
],
|
||||||
|
type: {
|
||||||
|
typeName: 'Aisle',
|
||||||
|
aisleType: aisleType,
|
||||||
|
aisleColor: aisleColor,
|
||||||
|
dotRadius: dotRadius,
|
||||||
|
gapLength: gapLength
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (aisleType === 'arrow-aisle') {
|
||||||
|
console.log();
|
||||||
|
} else if (aisleType === 'arrows-aisle') {
|
||||||
|
setTempAisle({
|
||||||
|
uuid: 'temp-aisle',
|
||||||
|
points: [
|
||||||
|
tempPoints[0],
|
||||||
|
{
|
||||||
|
uuid: 'temp-point',
|
||||||
|
position: [mousePosRef.current.x, mousePosRef.current.y, mousePosRef.current.z],
|
||||||
|
layer: activeLayer
|
||||||
|
}
|
||||||
|
],
|
||||||
|
type: {
|
||||||
|
typeName: 'Aisle',
|
||||||
|
aisleType: aisleType,
|
||||||
|
aisleColor: aisleColor,
|
||||||
|
aisleWidth: aisleWidth,
|
||||||
|
aisleLength: aisleLength,
|
||||||
|
gapLength: gapLength
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (aisleType === 'arc-aisle') {
|
||||||
|
console.log();
|
||||||
|
} else if (aisleType === 'circle-aisle') {
|
||||||
|
console.log();
|
||||||
|
} else if (aisleType === 'junction-aisle') {
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (tempAisle !== null) {
|
} else if (tempAisle !== null) {
|
||||||
setTempAisle(null);
|
setTempAisle(null);
|
||||||
|
@ -86,7 +154,7 @@ export default ReferenceAisle;
|
||||||
|
|
||||||
function SolidAisle({ aisle }: { readonly aisle: Aisle }) {
|
function SolidAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const shape = useMemo(() => {
|
const shape = useMemo(() => {
|
||||||
if (aisle.points.length < 2) return null;
|
if (aisle.points.length < 2 || aisle.type.aisleType !== 'solid-aisle') return null;
|
||||||
|
|
||||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||||
|
@ -133,13 +201,13 @@ function SolidAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
|
|
||||||
function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
|
function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const shapes = useMemo(() => {
|
const shapes = useMemo(() => {
|
||||||
if (aisle.points.length < 2) return [];
|
if (aisle.points.length < 2 || aisle.type.aisleType !== 'dashed-aisle') return [];
|
||||||
|
|
||||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||||
const width = aisle.type.aisleWidth || 0.1;
|
const width = aisle.type.aisleWidth || 0.1;
|
||||||
const dashLength = 0.5;
|
const dashLength = aisle.type.dashLength || 0.5;
|
||||||
const gapLength = 0.3;
|
const gapLength = aisle.type.gapLength || 0.3;
|
||||||
|
|
||||||
const direction = new THREE.Vector3().subVectors(end, start).normalize();
|
const direction = new THREE.Vector3().subVectors(end, start).normalize();
|
||||||
const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize();
|
const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize();
|
||||||
|
@ -198,12 +266,12 @@ function DashedAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
|
|
||||||
function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
|
function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const shapes = useMemo(() => {
|
const shapes = useMemo(() => {
|
||||||
if (aisle.points.length < 2) return [];
|
if (aisle.points.length < 2 || aisle.type.aisleType !== 'dotted-aisle') return [];
|
||||||
|
|
||||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||||
const width = aisle.type.aisleWidth || 0.1;
|
const width = aisle.type.dotRadius || 0.1;
|
||||||
const dotSpacing = 0.5;
|
const dotSpacing = aisle.type.gapLength || 0.5;
|
||||||
const dotRadius = width * 0.6;
|
const dotRadius = width * 0.6;
|
||||||
|
|
||||||
const totalLength = new THREE.Vector3().subVectors(end, start).length();
|
const totalLength = new THREE.Vector3().subVectors(end, start).length();
|
||||||
|
@ -250,13 +318,13 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
|
|
||||||
function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
|
function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const arrows = useMemo(() => {
|
const arrows = useMemo(() => {
|
||||||
if (aisle.points.length < 2) return [];
|
if (aisle.points.length < 2 || aisle.type.aisleType !== 'arrows-aisle') return [];
|
||||||
|
|
||||||
const start = new THREE.Vector3(...aisle.points[0].position);
|
const start = new THREE.Vector3(...aisle.points[0].position);
|
||||||
const end = new THREE.Vector3(...aisle.points[1].position);
|
const end = new THREE.Vector3(...aisle.points[1].position);
|
||||||
const width = aisle.type.aisleWidth || 0.1;
|
const width = aisle.type.aisleWidth || 0.1;
|
||||||
const arrowLength = 0.6;
|
const arrowLength = aisle.type.aisleLength || 0.6;
|
||||||
const spacing = 0.6;
|
const spacing = aisle.type.gapLength || 0.6;
|
||||||
|
|
||||||
const direction = new THREE.Vector3().subVectors(end, start);
|
const direction = new THREE.Vector3().subVectors(end, start);
|
||||||
const length = direction.length();
|
const length = direction.length();
|
||||||
|
@ -267,7 +335,7 @@ function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) {
|
||||||
const arrowShapes: { shape: THREE.Shape; position: THREE.Vector3; rotationY: number }[] = [];
|
const arrowShapes: { shape: THREE.Shape; position: THREE.Vector3; rotationY: number }[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const initialOffset = 0.6;
|
const initialOffset = arrowLength;
|
||||||
const center = new THREE.Vector3().copy(start).addScaledVector(direction, initialOffset + i * (arrowLength + spacing));
|
const center = new THREE.Vector3().copy(start).addScaledVector(direction, initialOffset + i * (arrowLength + spacing));
|
||||||
|
|
||||||
const shape = new THREE.Shape();
|
const shape = new THREE.Shape();
|
||||||
|
|
|
@ -10,7 +10,7 @@ interface ConnectionLine {
|
||||||
trigger: TriggerSchema;
|
trigger: TriggerSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Arrows({ connections }: { connections: ConnectionLine[] }) {
|
export function Arrows({ connections }: { readonly connections: ConnectionLine[] }) {
|
||||||
const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
|
const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
|
||||||
const groupRef = useRef<THREE.Group>(null);
|
const groupRef = useRef<THREE.Group>(null);
|
||||||
const { scene } = useThree();
|
const { scene } = useThree();
|
||||||
|
|
|
@ -10,8 +10,29 @@ interface AisleStore {
|
||||||
setPosition: (pointUuid: string, position: [number, number, number]) => void;
|
setPosition: (pointUuid: string, position: [number, number, number]) => void;
|
||||||
setLayer: (pointUuid: string, layer: number) => void;
|
setLayer: (pointUuid: string, layer: number) => void;
|
||||||
setColor: (aisleUuid: string, color: AisleColors) => void;
|
setColor: (aisleUuid: string, color: AisleColors) => void;
|
||||||
setWidth: (aisleUuid: string, width: number) => void;
|
|
||||||
|
// Type-specific setters
|
||||||
|
setSolidAisleWidth: (aisleUuid: string, width: number) => void;
|
||||||
|
setDashedAisleProperties: (
|
||||||
|
aisleUuid: string,
|
||||||
|
props: { aisleWidth?: number; dashLength?: number; gapLength?: number }
|
||||||
|
) => void;
|
||||||
|
setStrippedAisleWidth: (aisleUuid: string, width: number) => void;
|
||||||
|
setDottedAisleProperties: (
|
||||||
|
aisleUuid: string,
|
||||||
|
props: { dotRadius?: number; gapLength?: number }
|
||||||
|
) => void;
|
||||||
|
setArrowAisleWidth: (aisleUuid: string, width: number) => void;
|
||||||
|
setArrowsAisleProperties: (
|
||||||
|
aisleUuid: string,
|
||||||
|
props: { aisleWidth?: number; aisleLength?: number; gapLength?: number }
|
||||||
|
) => void;
|
||||||
|
setArcAisleWidth: (aisleUuid: string, width: number) => void;
|
||||||
|
setCircleAisleWidth: (aisleUuid: string, width: number) => void;
|
||||||
|
setJunctionAisleWidth: (aisleUuid: string, width: number) => void;
|
||||||
|
|
||||||
getAisleById: (uuid: string) => Aisle | undefined;
|
getAisleById: (uuid: string) => Aisle | undefined;
|
||||||
|
getAisleType: <T extends AisleType>(uuid: string) => T | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAisleStore = create<AisleStore>()(
|
export const useAisleStore = create<AisleStore>()(
|
||||||
|
@ -37,7 +58,7 @@ export const useAisleStore = create<AisleStore>()(
|
||||||
state.aisles = state.aisles.filter((a) => a.uuid !== uuid);
|
state.aisles = state.aisles.filter((a) => a.uuid !== uuid);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setPosition: (pointUuid: string, position: [number, number, number]) => set((state) => {
|
setPosition: (pointUuid, position) => set((state) => {
|
||||||
for (const aisle of state.aisles) {
|
for (const aisle of state.aisles) {
|
||||||
const point = aisle.points.find(p => p.uuid === pointUuid);
|
const point = aisle.points.find(p => p.uuid === pointUuid);
|
||||||
if (point) {
|
if (point) {
|
||||||
|
@ -47,7 +68,7 @@ export const useAisleStore = create<AisleStore>()(
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setLayer: (pointUuid: string, layer: number) => set((state) => {
|
setLayer: (pointUuid, layer) => set((state) => {
|
||||||
for (const aisle of state.aisles) {
|
for (const aisle of state.aisles) {
|
||||||
const point = aisle.points.find(p => p.uuid === pointUuid);
|
const point = aisle.points.find(p => p.uuid === pointUuid);
|
||||||
if (point) {
|
if (point) {
|
||||||
|
@ -57,16 +78,78 @@ export const useAisleStore = create<AisleStore>()(
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setColor: (aisleUuid: string, color: AisleColors) => set((state) => {
|
setColor: (aisleUuid, color) => set((state) => {
|
||||||
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
if (aisle) {
|
if (aisle) {
|
||||||
aisle.type.aisleColor = color;
|
aisle.type.aisleColor = color;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setWidth: (aisleUuid: string, width: number) => set((state) => {
|
// Type-specific property setters
|
||||||
|
setSolidAisleWidth: (aisleUuid, width) => set((state) => {
|
||||||
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
if (aisle) {
|
if (aisle && aisle.type.aisleType === 'solid-aisle') {
|
||||||
|
aisle.type.aisleWidth = width;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
setDashedAisleProperties: (aisleUuid, props) => set((state) => {
|
||||||
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
|
if (aisle && aisle.type.aisleType === 'dashed-aisle') {
|
||||||
|
if (props.aisleWidth !== undefined) aisle.type.aisleWidth = props.aisleWidth;
|
||||||
|
if (props.dashLength !== undefined) aisle.type.dashLength = props.dashLength;
|
||||||
|
if (props.gapLength !== undefined) aisle.type.gapLength = props.gapLength;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
setStrippedAisleWidth: (aisleUuid, width) => set((state) => {
|
||||||
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
|
if (aisle && aisle.type.aisleType === 'stripped-aisle') {
|
||||||
|
aisle.type.aisleWidth = width;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
setDottedAisleProperties: (aisleUuid, props) => set((state) => {
|
||||||
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
|
if (aisle && aisle.type.aisleType === 'dotted-aisle') {
|
||||||
|
if (props.dotRadius !== undefined) aisle.type.dotRadius = props.dotRadius;
|
||||||
|
if (props.gapLength !== undefined) aisle.type.gapLength = props.gapLength;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
setArrowAisleWidth: (aisleUuid, width) => set((state) => {
|
||||||
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
|
if (aisle && aisle.type.aisleType === 'arrow-aisle') {
|
||||||
|
aisle.type.aisleWidth = width;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
setArrowsAisleProperties: (aisleUuid, props) => set((state) => {
|
||||||
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
|
if (aisle && aisle.type.aisleType === 'arrows-aisle') {
|
||||||
|
if (props.aisleWidth !== undefined) aisle.type.aisleWidth = props.aisleWidth;
|
||||||
|
if (props.aisleLength !== undefined) aisle.type.aisleLength = props.aisleLength;
|
||||||
|
if (props.gapLength !== undefined) aisle.type.gapLength = props.gapLength;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
setArcAisleWidth: (aisleUuid, width) => set((state) => {
|
||||||
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
|
if (aisle && aisle.type.aisleType === 'arc-aisle') {
|
||||||
|
aisle.type.aisleWidth = width;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
setCircleAisleWidth: (aisleUuid, width) => set((state) => {
|
||||||
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
|
if (aisle && aisle.type.aisleType === 'circle-aisle') {
|
||||||
|
aisle.type.aisleWidth = width;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
setJunctionAisleWidth: (aisleUuid, width) => set((state) => {
|
||||||
|
const aisle = state.aisles.find(a => a.uuid === aisleUuid);
|
||||||
|
if (aisle && aisle.type.aisleType === 'junction-aisle') {
|
||||||
aisle.type.aisleWidth = width;
|
aisle.type.aisleWidth = width;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -74,5 +157,10 @@ export const useAisleStore = create<AisleStore>()(
|
||||||
getAisleById: (uuid) => {
|
getAisleById: (uuid) => {
|
||||||
return get().aisles.find((a) => a.uuid === uuid);
|
return get().aisles.find((a) => a.uuid === uuid);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getAisleType: <T extends AisleType>(uuid: string) => {
|
||||||
|
const aisle = get().aisles.find(a => a.uuid === uuid);
|
||||||
|
return aisle?.type as T | undefined;
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
);
|
);
|
|
@ -2,20 +2,55 @@ import { create } from 'zustand';
|
||||||
import { immer } from 'zustand/middleware/immer';
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
interface BuilderState {
|
interface BuilderState {
|
||||||
|
// Common properties
|
||||||
aisleType: AisleTypes;
|
aisleType: AisleTypes;
|
||||||
aisleWidth: number;
|
aisleWidth: number;
|
||||||
aisleColor: AisleColors;
|
aisleColor: AisleColors;
|
||||||
|
|
||||||
|
// Dashed aisle properties
|
||||||
|
dashLength: number;
|
||||||
|
gapLength: number;
|
||||||
|
|
||||||
|
// Dotted aisle properties
|
||||||
|
dotRadius: number;
|
||||||
|
|
||||||
|
// Arrows aisle properties
|
||||||
|
aisleLength: number;
|
||||||
|
|
||||||
|
// Setters for common properties
|
||||||
setAisleType: (type: AisleTypes) => void;
|
setAisleType: (type: AisleTypes) => void;
|
||||||
setAisleWidth: (width: number) => void;
|
setAisleWidth: (width: number) => void;
|
||||||
setAisleColor: (color: AisleColors) => void;
|
setAisleColor: (color: AisleColors) => void;
|
||||||
|
|
||||||
|
// Setters for dashed aisle
|
||||||
|
setDashLength: (length: number) => void;
|
||||||
|
setGapLength: (length: number) => void;
|
||||||
|
|
||||||
|
// Setters for dotted aisle
|
||||||
|
setDotRadius: (radius: number) => void;
|
||||||
|
|
||||||
|
// Setters for arrows aisle
|
||||||
|
setAisleLength: (length: number) => void;
|
||||||
|
|
||||||
|
// Batch setters
|
||||||
|
setDashedAisleProperties: (width: number, dashLength: number, gapLength: number) => void;
|
||||||
|
setDottedAisleProperties: (width: number, dotRadius: number, gapLength: number) => void;
|
||||||
|
setArrowsAisleProperties: (width: number, aisleLength: number, gapLength: number) => void;
|
||||||
setAisleProperties: (type: AisleTypes, width: number, color: AisleColors) => void;
|
setAisleProperties: (type: AisleTypes, width: number, color: AisleColors) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useBuilderStore = create<BuilderState>()(
|
export const useBuilderStore = create<BuilderState>()(
|
||||||
immer((set) => ({
|
immer((set) => ({
|
||||||
|
// Default values
|
||||||
aisleType: 'solid-aisle',
|
aisleType: 'solid-aisle',
|
||||||
aisleWidth: 0.1,
|
aisleWidth: 0.1,
|
||||||
aisleColor: 'yellow',
|
aisleColor: 'yellow',
|
||||||
|
dashLength: 0.5,
|
||||||
|
gapLength: 0.3,
|
||||||
|
dotRadius: 0.1,
|
||||||
|
aisleLength: 0.6,
|
||||||
|
|
||||||
|
// Individual setters
|
||||||
setAisleType: (type) => {
|
setAisleType: (type) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.aisleType = type;
|
state.aisleType = type;
|
||||||
|
@ -31,6 +66,52 @@ export const useBuilderStore = create<BuilderState>()(
|
||||||
state.aisleColor = color;
|
state.aisleColor = color;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
setDashLength: (length) => {
|
||||||
|
set((state) => {
|
||||||
|
state.dashLength = length;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setGapLength: (length) => {
|
||||||
|
set((state) => {
|
||||||
|
state.gapLength = length;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setDotRadius: (radius) => {
|
||||||
|
set((state) => {
|
||||||
|
state.dotRadius = radius;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setAisleLength: (length) => {
|
||||||
|
set((state) => {
|
||||||
|
state.aisleLength = length;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Batch setters
|
||||||
|
setDashedAisleProperties: (width, dashLength, gapLength) => {
|
||||||
|
set((state) => {
|
||||||
|
state.aisleType = 'dashed-aisle';
|
||||||
|
state.aisleWidth = width;
|
||||||
|
state.dashLength = dashLength;
|
||||||
|
state.gapLength = gapLength;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setDottedAisleProperties: (width, dotRadius, gapLength) => {
|
||||||
|
set((state) => {
|
||||||
|
state.aisleType = 'dotted-aisle';
|
||||||
|
state.aisleWidth = width;
|
||||||
|
state.dotRadius = dotRadius;
|
||||||
|
state.gapLength = gapLength;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setArrowsAisleProperties: (width, aisleLength, gapLength) => {
|
||||||
|
set((state) => {
|
||||||
|
state.aisleType = 'arrows-aisle';
|
||||||
|
state.aisleWidth = width;
|
||||||
|
state.aisleLength = aisleLength;
|
||||||
|
state.gapLength = gapLength;
|
||||||
|
});
|
||||||
|
},
|
||||||
setAisleProperties: (type, width, color) => {
|
setAisleProperties: (type, width, color) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.aisleType = type;
|
state.aisleType = type;
|
||||||
|
|
|
@ -41,13 +41,76 @@ type AisleTypes = | 'solid-aisle' | 'dashed-aisle' | 'stripped-aisle' | 'dotted-
|
||||||
|
|
||||||
type AisleColors = | 'gray' | 'yellow' | 'green' | 'orange' | 'blue' | 'purple' | 'red' | 'bright green' | 'yellow-black' | 'white-black'
|
type AisleColors = | 'gray' | 'yellow' | 'green' | 'orange' | 'blue' | 'purple' | 'red' | 'bright green' | 'yellow-black' | 'white-black'
|
||||||
|
|
||||||
interface AisleType {
|
interface SolidAisle {
|
||||||
typeName: 'Aisle';
|
typeName: 'Aisle';
|
||||||
aisleType: AisleTypes;
|
aisleType: 'solid-aisle';
|
||||||
aisleColor: AisleColors;
|
aisleColor: AisleColors;
|
||||||
aisleWidth: number;
|
aisleWidth: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DashedAisle {
|
||||||
|
typeName: 'Aisle';
|
||||||
|
aisleType: 'dashed-aisle';
|
||||||
|
aisleColor: AisleColors;
|
||||||
|
aisleWidth: number;
|
||||||
|
dashLength: number;
|
||||||
|
gapLength: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StrippedAisle {
|
||||||
|
typeName: 'Aisle';
|
||||||
|
aisleType: 'stripped-aisle';
|
||||||
|
aisleColor: AisleColors;
|
||||||
|
aisleWidth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DottedAisle {
|
||||||
|
typeName: 'Aisle';
|
||||||
|
aisleType: 'dotted-aisle';
|
||||||
|
aisleColor: AisleColors;
|
||||||
|
dotRadius: number;
|
||||||
|
gapLength: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArrowAisle {
|
||||||
|
typeName: 'Aisle';
|
||||||
|
aisleType: 'arrow-aisle';
|
||||||
|
aisleColor: AisleColors;
|
||||||
|
aisleWidth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArrowsAisle {
|
||||||
|
typeName: 'Aisle';
|
||||||
|
aisleType: 'arrows-aisle';
|
||||||
|
aisleColor: AisleColors;
|
||||||
|
aisleWidth: number;
|
||||||
|
aisleLength: number;
|
||||||
|
gapLength: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArcAisle {
|
||||||
|
typeName: 'Aisle';
|
||||||
|
aisleType: 'arc-aisle';
|
||||||
|
aisleColor: AisleColors;
|
||||||
|
aisleWidth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CircleAisle {
|
||||||
|
typeName: 'Aisle';
|
||||||
|
aisleType: 'circle-aisle';
|
||||||
|
aisleColor: AisleColors;
|
||||||
|
aisleWidth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JunctionAisle {
|
||||||
|
typeName: 'Aisle';
|
||||||
|
aisleType: 'junction-aisle';
|
||||||
|
aisleColor: AisleColors;
|
||||||
|
aisleWidth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type AisleType = SolidAisle | DashedAisle | StrippedAisle | DottedAisle | ArrowAisle | ArrowsAisle | ArcAisle | CircleAisle | JunctionAisle;
|
||||||
|
|
||||||
interface Aisle {
|
interface Aisle {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
points: [Point, Point];
|
points: [Point, Point];
|
||||||
|
|
Loading…
Reference in New Issue