import { useCubesContext } from "@/contexts/cubes-context"; import { FacingDirection } from "./consts"; import { RotationPanel } from "./rotation-panel"; import { Group } from "three"; import { Fragment, useRef } from "react"; import { useFrame } from "@react-three/fiber"; type RotateArgs = { rotatingFaceDirection: FacingDirection; rotatingDirection: "clockwise" | "counter-clockwise"; rotatingGroup: Group; }; type RotatorProps = { cubeSpeed: number; }; export const Rotator = ({ cubeSpeed }: RotatorProps) => { const { getCubes, cubeGroupRef } = useCubesContext(); const isRotating = useRef(false); const rotateArgs = useRef({ rotatingFaceDirection: "front", rotatingDirection: "clockwise", rotatingGroup: new Group(), }); useFrame((state, delta) => { const { rotatingFaceDirection, rotatingDirection, rotatingGroup } = rotateArgs.current; const cubeGroup = cubeGroupRef.current; if (!isRotating.current || !cubeGroup) return; let sign = 0; switch (rotatingFaceDirection) { case "front": sign = rotatingDirection === "clockwise" ? -1 : 1; rotatingGroup.rotation.z += sign * delta * cubeSpeed; if (Math.abs(rotatingGroup.rotation.z) > Math.PI / 2) { rotatingGroup.rotation.z = (Math.PI / 2) * sign; isRotating.current = false; } break; case "back": sign = rotatingDirection === "clockwise" ? 1 : -1; rotatingGroup.rotation.z += sign * delta * cubeSpeed; if (Math.abs(rotatingGroup.rotation.z) > Math.PI / 2) { rotatingGroup.rotation.z = (Math.PI / 2) * sign; isRotating.current = false; } break; case "left": sign = rotatingDirection === "clockwise" ? 1 : -1; rotatingGroup.rotation.x += sign * delta * cubeSpeed; if (Math.abs(rotatingGroup.rotation.x) > Math.PI / 2) { rotatingGroup.rotation.x = (Math.PI / 2) * sign; isRotating.current = false; } break; case "right": sign = rotatingDirection === "clockwise" ? -1 : 1; rotatingGroup.rotation.x += sign * delta * cubeSpeed; if (Math.abs(rotatingGroup.rotation.x) > Math.PI / 2) { rotatingGroup.rotation.x = (Math.PI / 2) * sign; isRotating.current = false; } break; case "top": sign = rotatingDirection === "clockwise" ? -1 : 1; rotatingGroup.rotation.y += sign * delta * cubeSpeed; if (Math.abs(rotatingGroup.rotation.y) > Math.PI / 2) { rotatingGroup.rotation.y = (Math.PI / 2) * sign; isRotating.current = false; } break; case "bottom": sign = rotatingDirection === "clockwise" ? 1 : -1; rotatingGroup.rotation.y += sign * delta * cubeSpeed; if (Math.abs(rotatingGroup.rotation.y) > Math.PI / 2) { rotatingGroup.rotation.y = (Math.PI / 2) * sign; isRotating.current = false; } break; } if (isRotating.current) return; const children = [...rotatingGroup.children]; children.forEach((child) => cubeGroup.attach(child)); cubeGroup.remove(rotatingGroup); }); const handleClick = ( facingDirection: FacingDirection, direction: "clockwise" | "counter-clockwise", ) => { if (isRotating.current || !cubeGroupRef.current) return; const cubes = getCubes(facingDirection); rotateArgs.current.rotatingFaceDirection = facingDirection; rotateArgs.current.rotatingDirection = direction; rotateArgs.current.rotatingGroup = new Group(); cubeGroupRef.current.add(rotateArgs.current.rotatingGroup); cubes.forEach((cube) => rotateArgs.current.rotatingGroup.attach(cube)); isRotating.current = true; }; return ( <> {["front", "back", "left", "right", "top", "bottom"].map( (facingDirection) => ( ), )} ); };