refactor: Enhance Point component with drag functionality and update state management in aisle store
This commit is contained in:
parent
16e3f51448
commit
e2fab37f0f
|
@ -2,11 +2,19 @@ import * as THREE from 'three';
|
||||||
import * as Constants from '../../../types/world/worldConstants';
|
import * as Constants from '../../../types/world/worldConstants';
|
||||||
import { useRef, useState, useEffect, useMemo } from 'react';
|
import { useRef, useState, useEffect, useMemo } from 'react';
|
||||||
import { useToolMode } from '../../../store/builder/store';
|
import { useToolMode } from '../../../store/builder/store';
|
||||||
|
import { DragControls } from '@react-three/drei';
|
||||||
|
import { useAisleStore } from '../../../store/builder/useAisleStore';
|
||||||
|
import { useThree } from '@react-three/fiber';
|
||||||
|
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
|
||||||
|
|
||||||
function Point({ point, userData }: { readonly point: Point, readonly userData: any }) {
|
function Point({ point, userData }: { readonly point: Point, readonly userData: any }) {
|
||||||
const materialRef = useRef<THREE.ShaderMaterial>(null);
|
const materialRef = useRef<THREE.ShaderMaterial>(null);
|
||||||
|
const { raycaster, camera, scene, pointer } = useThree();
|
||||||
|
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
const { toolMode } = useToolMode();
|
const { toolMode } = useToolMode();
|
||||||
|
const { setPosition } = useAisleStore();
|
||||||
|
const { hoveredPoint, setHoveredPoint } = useBuilderStore();
|
||||||
|
|
||||||
const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
|
const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
|
||||||
const defaultInnerColor = Constants.pointConfig.defaultInnerColor;
|
const defaultInnerColor = Constants.pointConfig.defaultInnerColor;
|
||||||
|
@ -29,31 +37,73 @@ function Point({ point, userData }: { readonly point: Point, readonly userData:
|
||||||
uInnerColor: { value: new THREE.Color(defaultInnerColor) },
|
uInnerColor: { value: new THREE.Color(defaultInnerColor) },
|
||||||
}), [borderColor, defaultInnerColor]);
|
}), [borderColor, defaultInnerColor]);
|
||||||
|
|
||||||
|
const handleDrag = (point: Point) => {
|
||||||
|
if (toolMode === 'move' && isHovered) {
|
||||||
|
raycaster.setFromCamera(pointer, camera);
|
||||||
|
const intersectionPoint = new THREE.Vector3();
|
||||||
|
const position = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||||
|
if (userData.pointType === 'Aisle') {
|
||||||
|
if (position) {
|
||||||
|
setPosition(point.uuid, [position.x, position.y, position.z]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDragEnd = (point: Point) => {
|
||||||
|
console.log('point: ', point);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (hoveredPoint && hoveredPoint.uuid !== point.uuid) {
|
||||||
|
setIsHovered(false);
|
||||||
|
}
|
||||||
|
}, [hoveredPoint])
|
||||||
|
|
||||||
if (!point) {
|
if (!point) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<DragControls
|
||||||
|
axisLock='y'
|
||||||
|
autoTransform={false}
|
||||||
|
onDrag={() => { handleDrag(point) }}
|
||||||
|
onDragEnd={() => { handleDragEnd(point) }}
|
||||||
|
>
|
||||||
<mesh
|
<mesh
|
||||||
uuid={point.uuid}
|
uuid={point.uuid}
|
||||||
position={new THREE.Vector3(...point.position)}
|
position={new THREE.Vector3(...point.position)}
|
||||||
onPointerOver={() => setIsHovered(true)}
|
onPointerOver={() => {
|
||||||
onPointerOut={() => setIsHovered(false)}
|
if (!hoveredPoint) {
|
||||||
|
setHoveredPoint(point);
|
||||||
|
setIsHovered(true)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onPointerOut={() => {
|
||||||
|
if (hoveredPoint && hoveredPoint.uuid === point.uuid) {
|
||||||
|
setHoveredPoint(null);
|
||||||
|
}
|
||||||
|
setIsHovered(false)
|
||||||
|
}}
|
||||||
userData={userData}
|
userData={userData}
|
||||||
>
|
>
|
||||||
<boxGeometry args={boxScale} />
|
<boxGeometry args={boxScale} />
|
||||||
<shaderMaterial
|
<shaderMaterial
|
||||||
ref={materialRef}
|
ref={materialRef}
|
||||||
uniforms={uniforms}
|
uniforms={uniforms}
|
||||||
vertexShader={`
|
vertexShader={
|
||||||
|
`
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vUv = uv;
|
vUv = uv;
|
||||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||||
}
|
}
|
||||||
`}
|
`
|
||||||
fragmentShader={`
|
}
|
||||||
|
fragmentShader={
|
||||||
|
`
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
uniform vec3 uColor;
|
uniform vec3 uColor;
|
||||||
uniform vec3 uInnerColor;
|
uniform vec3 uInnerColor;
|
||||||
|
@ -61,16 +111,17 @@ function Point({ point, userData }: { readonly point: Point, readonly userData:
|
||||||
void main() {
|
void main() {
|
||||||
// Define the size of the white square as a proportion of the face
|
// Define the size of the white square as a proportion of the face
|
||||||
float borderThickness = 0.2; // Adjust this value for border thickness
|
float borderThickness = 0.2; // Adjust this value for border thickness
|
||||||
if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness &&
|
if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
|
||||||
vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
|
|
||||||
gl_FragColor = vec4(uInnerColor, 1.0); // Inner square
|
gl_FragColor = vec4(uInnerColor, 1.0); // Inner square
|
||||||
} else {
|
} else {
|
||||||
gl_FragColor = vec4(uColor, 1.0); // Border
|
gl_FragColor = vec4(uColor, 1.0); // Border
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`}
|
`
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
|
</DragControls>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,6 @@ export const useAisleStore = create<AisleStore>()(
|
||||||
const point = aisle.points.find(p => p.uuid === pointUuid);
|
const point = aisle.points.find(p => p.uuid === pointUuid);
|
||||||
if (point) {
|
if (point) {
|
||||||
point.position = position;
|
point.position = position;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -73,7 +72,6 @@ export const useAisleStore = create<AisleStore>()(
|
||||||
const point = aisle.points.find(p => p.uuid === pointUuid);
|
const point = aisle.points.find(p => p.uuid === pointUuid);
|
||||||
if (point) {
|
if (point) {
|
||||||
point.layer = layer;
|
point.layer = layer;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -3,6 +3,9 @@ import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
interface BuilderState {
|
interface BuilderState {
|
||||||
// Common properties
|
// Common properties
|
||||||
|
|
||||||
|
hoveredPoint: Point | null;
|
||||||
|
|
||||||
aisleType: AisleTypes;
|
aisleType: AisleTypes;
|
||||||
aisleWidth: number;
|
aisleWidth: number;
|
||||||
aisleColor: AisleColors;
|
aisleColor: AisleColors;
|
||||||
|
@ -18,6 +21,9 @@ interface BuilderState {
|
||||||
aisleLength: number;
|
aisleLength: number;
|
||||||
|
|
||||||
// Setters for common properties
|
// Setters for common properties
|
||||||
|
|
||||||
|
setHoveredPoint: (point: Point | 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;
|
||||||
|
@ -42,6 +48,9 @@ interface BuilderState {
|
||||||
export const useBuilderStore = create<BuilderState>()(
|
export const useBuilderStore = create<BuilderState>()(
|
||||||
immer((set) => ({
|
immer((set) => ({
|
||||||
// Default values
|
// Default values
|
||||||
|
|
||||||
|
hoveredPoint: null,
|
||||||
|
|
||||||
aisleType: 'solid-aisle',
|
aisleType: 'solid-aisle',
|
||||||
aisleWidth: 0.1,
|
aisleWidth: 0.1,
|
||||||
aisleColor: 'yellow',
|
aisleColor: 'yellow',
|
||||||
|
@ -51,6 +60,13 @@ export const useBuilderStore = create<BuilderState>()(
|
||||||
aisleLength: 0.6,
|
aisleLength: 0.6,
|
||||||
|
|
||||||
// Individual setters
|
// Individual setters
|
||||||
|
|
||||||
|
setHoveredPoint: (point: Point | null) => {
|
||||||
|
set((state) => {
|
||||||
|
state.hoveredPoint = point;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
setAisleType: (type) => {
|
setAisleType: (type) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.aisleType = type;
|
state.aisleType = type;
|
||||||
|
|
Loading…
Reference in New Issue