File size: 2,330 Bytes
1afe868
ca23eb9
1afe868
7994c21
1afe868
 
 
 
e95d66b
1bc1cd0
 
1afe868
 
 
 
 
 
1bc1cd0
 
7994c21
 
 
 
e95d66b
 
ca23eb9
e95d66b
 
7994c21
ca23eb9
 
ec43676
20ba9a1
 
 
 
 
ec43676
7994c21
 
 
 
 
 
 
7f7b2cc
ca23eb9
 
 
5438f67
ca23eb9
 
 
7f7b2cc
 
 
 
 
 
 
 
1bc1cd0
e95d66b
7994c21
e95d66b
1afe868
e95d66b
1bc1cd0
ca23eb9
 
1bc1cd0
 
1afe868
1bc1cd0
1afe868
1bc1cd0
 
 
e95d66b
 
7994c21
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
'use client';

import { RoundedBox } from '@react-three/drei';
import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
import { Mesh } from 'three';

import { FacingDirection, Rotations } from './consts';
import { rotationController } from './rotation-controller';

// Standard Rubik's cube colors
const CUBE_COLORS = {
  front: '#ff0000', // Red
  back: '#ff00ff', // Purple
  left: '#00ff00', // Green
  right: '#0000ff', // Blue
  top: '#ffff00', // Yellow
  bottom: '#ffffff', // White
};

export type CubePieceRef = {
  resetPosition: () => void;
};

type CubePieceProps = {
  roughness: number;
  initialPosition: [number, number, number];
};

export const CubePiece = forwardRef<CubePieceRef, CubePieceProps>(({ roughness, initialPosition }, ref) => {
  const [x, y, z] = initialPosition;

  const meshRef = useRef<Mesh | null>(null);
  useEffect(() => {
    if (meshRef.current) {
      rotationController.addCube(meshRef.current);
    }
  }, [meshRef]);

  useImperativeHandle(ref, () => ({
    resetPosition: () => {
      meshRef.current?.position.set(x, y, z);
      meshRef.current?.rotation.set(0, 0, 0);
    },
  }));

  const visibleFaces: Record<FacingDirection, boolean> = {
    front: z > 0,
    back: z < 0,
    left: x < 0,
    right: x > 0,
    top: y > 0,
    bottom: y < 0,
  };
  const positions: Record<FacingDirection, [number, number, number]> = {
    front: [0, 0, 0.48],
    back: [0, 0, -0.48],
    left: [-0.48, 0, 0],
    right: [0.48, 0, 0],
    top: [0, 0.48, 0],
    bottom: [0, -0.48, 0],
  };

  return (
    <mesh position={[x, y, z]} ref={meshRef}>
      <RoundedBox args={[0.95, 0.95, 0.95]} radius={0.05} smoothness={4}>
        <meshStandardMaterial color="#2a2a2a" metalness={1} roughness={roughness} />
      </RoundedBox>

      {Object.entries(visibleFaces).map(([face, isVisible]) => {
        if (!isVisible) return null;
        const color = CUBE_COLORS[face as keyof typeof CUBE_COLORS];
        return (
          <mesh key={face} position={positions[face as FacingDirection]} rotation={Rotations[face as FacingDirection]}>
            <planeGeometry args={[0.8, 0.8]} />
            <meshStandardMaterial color={color} metalness={1} roughness={roughness} />
          </mesh>
        );
      })}
    </mesh>
  );
});

CubePiece.displayName = 'CubePiece';