first commit
This commit is contained in:
227
app/src/modules/builder/point/point.tsx
Normal file
227
app/src/modules/builder/point/point.tsx
Normal file
@@ -0,0 +1,227 @@
|
||||
import * as THREE from 'three';
|
||||
import * as Constants from '../../../types/world/worldConstants';
|
||||
import { useRef, useState, useEffect, useMemo } from 'react';
|
||||
import { useDeletePointOrLine, 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';
|
||||
import { usePointSnapping } from './helpers/usePointSnapping';
|
||||
import { useAislePointSnapping } from './helpers/useAisleDragSnap';
|
||||
import { useWallStore } from '../../../store/builder/useWallStore';
|
||||
import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { createAisleApi } from '../../../services/factoryBuilder/aisle/createAisleApi';
|
||||
|
||||
function Point({ point }: { readonly point: Point }) {
|
||||
const materialRef = useRef<THREE.ShaderMaterial>(null);
|
||||
const { raycaster, camera, 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: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = useAisleStore();
|
||||
const { setPosition: setWallPosition, removePoint: removeWallPoint } = useWallStore();
|
||||
const { snapPosition } = useAislePointSnapping(point);
|
||||
const { checkSnapForAisle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position });
|
||||
const { hoveredPoint, setHoveredPoint } = useBuilderStore();
|
||||
const { deletePointOrLine } = useDeletePointOrLine();
|
||||
const { projectId } = useParams();
|
||||
const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
|
||||
const colors = getColor(point);
|
||||
|
||||
function getColor(point: Point) {
|
||||
if (point.pointType === 'Aisle') {
|
||||
return {
|
||||
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
|
||||
defaultOuterColor: Constants.pointConfig.aisleOuterColor,
|
||||
defaultDeleteColor: Constants.pointConfig.deleteColor,
|
||||
}
|
||||
} else if (point.pointType === 'Floor') {
|
||||
return {
|
||||
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
|
||||
defaultOuterColor: Constants.pointConfig.floorOuterColor,
|
||||
defaultDeleteColor: Constants.pointConfig.deleteColor,
|
||||
}
|
||||
} else if (point.pointType === 'Wall') {
|
||||
return {
|
||||
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
|
||||
defaultOuterColor: Constants.pointConfig.wallOuterColor,
|
||||
defaultDeleteColor: Constants.pointConfig.deleteColor,
|
||||
}
|
||||
} else if (point.pointType === 'Zone') {
|
||||
return {
|
||||
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
|
||||
defaultOuterColor: Constants.pointConfig.zoneOuterColor,
|
||||
defaultDeleteColor: Constants.pointConfig.deleteColor,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
|
||||
defaultOuterColor: Constants.pointConfig.defaultOuterColor,
|
||||
defaultDeleteColor: Constants.pointConfig.deleteColor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (materialRef.current && (toolMode === 'move' || deletePointOrLine)) {
|
||||
let innerColor;
|
||||
let outerColor;
|
||||
if (isHovered) {
|
||||
innerColor = deletePointOrLine ? colors.defaultDeleteColor : colors.defaultOuterColor;
|
||||
outerColor = deletePointOrLine ? colors.defaultDeleteColor : colors.defaultOuterColor;
|
||||
} else {
|
||||
innerColor = colors.defaultInnerColor;
|
||||
outerColor = colors.defaultOuterColor;
|
||||
}
|
||||
materialRef.current.uniforms.uInnerColor.value.set(innerColor);
|
||||
materialRef.current.uniforms.uOuterColor.value.set(outerColor);
|
||||
materialRef.current.uniformsNeedUpdate = true;
|
||||
} else if (materialRef.current && toolMode !== 'move') {
|
||||
materialRef.current.uniforms.uInnerColor.value.set(colors.defaultInnerColor);
|
||||
materialRef.current.uniforms.uOuterColor.value.set(colors.defaultOuterColor);
|
||||
materialRef.current.uniformsNeedUpdate = true;
|
||||
}
|
||||
}, [isHovered, colors.defaultInnerColor, colors.defaultOuterColor, colors.defaultDeleteColor, toolMode, deletePointOrLine]);
|
||||
|
||||
const uniforms = useMemo(() => ({
|
||||
uOuterColor: { value: new THREE.Color(colors.defaultOuterColor) },
|
||||
uInnerColor: { value: new THREE.Color(colors.defaultInnerColor) },
|
||||
}), [colors.defaultInnerColor, colors.defaultOuterColor]);
|
||||
|
||||
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 (point.pointType === 'Aisle') {
|
||||
if (position) {
|
||||
const newPosition: [number, number, number] = [position.x, position.y, position.z];
|
||||
const aisleSnappedPosition = snapPosition(newPosition);
|
||||
const finalSnappedPosition = checkSnapForAisle(aisleSnappedPosition.position);
|
||||
|
||||
setAislePosition(point.pointUuid, finalSnappedPosition.position);
|
||||
|
||||
}
|
||||
} else if (point.pointType === 'Wall') {
|
||||
if (position) {
|
||||
const newPosition: [number, number, number] = [position.x, position.y, position.z];
|
||||
|
||||
setWallPosition(point.pointUuid, newPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleDragEnd = (point: Point) => {
|
||||
if (deletePointOrLine) return;
|
||||
if (point.pointType === 'Aisle') {
|
||||
const updatedAisles = getAislesByPointId(point.pointUuid);
|
||||
if (updatedAisles.length > 0 && projectId) {
|
||||
updatedAisles.forEach((updatedAisle) => {
|
||||
createAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId)
|
||||
})
|
||||
}
|
||||
} else if (point.pointType === 'Wall') {
|
||||
// console.log('Wall after drag: ', point);
|
||||
}
|
||||
}
|
||||
|
||||
const handlePointClick = (point: Point) => {
|
||||
if (deletePointOrLine) {
|
||||
if (point.pointType === 'Aisle') {
|
||||
const removedAisles = removeAislePoint(point.pointUuid);
|
||||
if (removedAisles.length > 0) {
|
||||
removedAisles.forEach(aisle => {
|
||||
if (projectId)
|
||||
deleteAisleApi(aisle.aisleUuid, projectId)
|
||||
});
|
||||
setHoveredPoint(null);
|
||||
}
|
||||
}
|
||||
if (point.pointType === 'Wall') {
|
||||
const removedAisles = removeWallPoint(point.pointUuid);
|
||||
if (removedAisles.length > 0) {
|
||||
setHoveredPoint(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (hoveredPoint && hoveredPoint.pointUuid !== point.pointUuid) {
|
||||
setIsHovered(false);
|
||||
}
|
||||
}, [hoveredPoint])
|
||||
|
||||
if (!point) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<DragControls
|
||||
axisLock='y'
|
||||
autoTransform={false}
|
||||
onDrag={() => { handleDrag(point) }}
|
||||
onDragEnd={() => { handleDragEnd(point) }}
|
||||
>
|
||||
<mesh
|
||||
key={point.pointUuid}
|
||||
uuid={point.pointUuid}
|
||||
name={`${point.pointType}-Point`}
|
||||
position={new THREE.Vector3(...point.position)}
|
||||
onClick={() => {
|
||||
handlePointClick(point);
|
||||
}}
|
||||
onPointerOver={() => {
|
||||
if (!hoveredPoint) {
|
||||
setHoveredPoint(point);
|
||||
setIsHovered(true)
|
||||
}
|
||||
}}
|
||||
onPointerOut={() => {
|
||||
if (hoveredPoint && hoveredPoint.pointUuid === point.pointUuid) {
|
||||
setHoveredPoint(null);
|
||||
}
|
||||
setIsHovered(false)
|
||||
}}
|
||||
userData={point}
|
||||
>
|
||||
<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 uOuterColor;
|
||||
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(uOuterColor, 1.0); // Border
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
/>
|
||||
</mesh>
|
||||
</DragControls>
|
||||
);
|
||||
}
|
||||
|
||||
export default Point;
|
||||
Reference in New Issue
Block a user