import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react'; import { Group } from 'three'; import { RotationStep } from './consts'; import { CubePiece, CubePieceRef } from './cube-piece'; import { rotationController } from './rotation-controller'; import { Rotator, RotatorRef } from './rotator'; const CUBE_POSITIONS: Array<[number, number, number]> = []; for (let x = -0.5; x <= 0.5; x += 1) { for (let y = -0.5; y <= 0.5; y += 1) { for (let z = -0.5; z <= 0.5; z += 1) { CUBE_POSITIONS.push([x, y, z]); } } } export type RubiksCubeRef = { rotate: (steps: Array) => void; reset: () => void; }; type RubiksCubeProps = { cubeRoughness: number; cubeSpeed: number; }; export const RubiksCube = forwardRef(({ cubeRoughness, cubeSpeed }, ref) => { const cubeGroupRef = useRef(null); const rotatorRef = useRef(null); const cubePieceRefs = useRef>(new Map()); useImperativeHandle(ref, () => ({ rotate: (steps: Array) => rotatorRef.current?.rotate(steps), reset: () => { rotationController.stopRotation(() => { cubePieceRefs.current.forEach((cubePieceRef) => { cubePieceRef.resetPosition(); }); }); }, })); useEffect(() => { if (cubeGroupRef.current) rotationController.setCubeGroup(cubeGroupRef.current); }, [cubeGroupRef]); return ( <> {CUBE_POSITIONS.map((position) => { const positionKey = position.join(','); return ( { if (ref) { cubePieceRefs.current.set(positionKey, ref); } else { cubePieceRefs.current.delete(positionKey); } }} initialPosition={position} roughness={cubeRoughness} /> ); })} ); }); RubiksCube.displayName = 'RubiksCube';