Dwinzo_dev/app/src/modules/builder/point/point.tsx

128 lines
5.0 KiB
TypeScript
Raw Normal View History

import * as THREE from 'three';
import * as Constants from '../../../types/world/worldConstants';
import { useRef, useState, useEffect, useMemo } from 'react';
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 }) {
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 { toolMode } = useToolMode();
const { setPosition } = useAisleStore();
const { hoveredPoint, setHoveredPoint } = useBuilderStore();
const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
const defaultInnerColor = Constants.pointConfig.defaultInnerColor;
const borderColor = Constants.pointConfig.aisleOuterColor;
useEffect(() => {
if (materialRef.current && toolMode === 'move') {
materialRef.current.uniforms.uInnerColor.value.set(
isHovered ? borderColor : defaultInnerColor
);
materialRef.current.uniformsNeedUpdate = true;
} else if (materialRef.current && toolMode !== 'move') {
materialRef.current.uniforms.uInnerColor.value.set(defaultInnerColor);
materialRef.current.uniformsNeedUpdate = true;
}
}, [isHovered, borderColor, defaultInnerColor, toolMode]);
const uniforms = useMemo(() => ({
uColor: { value: new THREE.Color(borderColor) },
uInnerColor: { value: new THREE.Color(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) {
return null;
}
return (
<DragControls
axisLock='y'
autoTransform={false}
onDrag={() => { handleDrag(point) }}
onDragEnd={() => { handleDragEnd(point) }}
>
<mesh
uuid={point.uuid}
position={new THREE.Vector3(...point.position)}
onPointerOver={() => {
if (!hoveredPoint) {
setHoveredPoint(point);
setIsHovered(true)
}
}}
onPointerOut={() => {
if (hoveredPoint && hoveredPoint.uuid === point.uuid) {
setHoveredPoint(null);
}
setIsHovered(false)
}}
userData={userData}
>
<boxGeometry args={boxScale} />
<shaderMaterial
ref={materialRef}
uniforms={uniforms}
vertexShader={
`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`
}
fragmentShader={
`
varying vec2 vUv;
uniform vec3 uColor;
uniform vec3 uInnerColor;
void main() {
// Define the size of the white square as a proportion of the face
float borderThickness = 0.2; // Adjust this value for border thickness
if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
gl_FragColor = vec4(uInnerColor, 1.0); // Inner square
} else {
gl_FragColor = vec4(uColor, 1.0); // Border
}
}
`
}
/>
</mesh>
</DragControls>
);
}
export default Point;