imwithye commited on
Commit
7994c21
·
1 Parent(s): 5c4a167

implement reset

Browse files
src/components/cube-piece.tsx CHANGED
@@ -1,7 +1,7 @@
1
  'use client';
2
 
3
  import { RoundedBox } from '@react-three/drei';
4
- import { useEffect, useRef, useState } from 'react';
5
  import { Mesh } from 'three';
6
 
7
  import { FacingDirection, Rotations } from './consts';
@@ -17,14 +17,17 @@ const CUBE_COLORS = {
17
  bottom: '#ffffff', // White
18
  };
19
 
 
 
 
 
20
  type CubePieceProps = {
21
  roughness: number;
22
  initialPosition: [number, number, number];
23
  };
24
 
25
- export const CubePiece = ({ roughness, initialPosition }: CubePieceProps) => {
26
  const [x, y, z] = initialPosition;
27
- const [position] = useState<[number, number, number]>([x, y, z]);
28
 
29
  const meshRef = useRef<Mesh | null>(null);
30
  useEffect(() => {
@@ -33,6 +36,13 @@ export const CubePiece = ({ roughness, initialPosition }: CubePieceProps) => {
33
  }
34
  }, [meshRef]);
35
 
 
 
 
 
 
 
 
36
  const visibleFaces: Record<FacingDirection, boolean> = {
37
  front: z > 0,
38
  back: z < 0,
@@ -51,7 +61,7 @@ export const CubePiece = ({ roughness, initialPosition }: CubePieceProps) => {
51
  };
52
 
53
  return (
54
- <mesh position={position} ref={meshRef}>
55
  <RoundedBox args={[0.95, 0.95, 0.95]} radius={0.05} smoothness={4}>
56
  <meshStandardMaterial color="#2a2a2a" metalness={1} roughness={roughness} />
57
  </RoundedBox>
@@ -68,4 +78,6 @@ export const CubePiece = ({ roughness, initialPosition }: CubePieceProps) => {
68
  })}
69
  </mesh>
70
  );
71
- };
 
 
 
1
  'use client';
2
 
3
  import { RoundedBox } from '@react-three/drei';
4
+ import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
5
  import { Mesh } from 'three';
6
 
7
  import { FacingDirection, Rotations } from './consts';
 
17
  bottom: '#ffffff', // White
18
  };
19
 
20
+ export type CubePieceRef = {
21
+ resetPosition: () => void;
22
+ };
23
+
24
  type CubePieceProps = {
25
  roughness: number;
26
  initialPosition: [number, number, number];
27
  };
28
 
29
+ export const CubePiece = forwardRef<CubePieceRef, CubePieceProps>(({ roughness, initialPosition }, ref) => {
30
  const [x, y, z] = initialPosition;
 
31
 
32
  const meshRef = useRef<Mesh | null>(null);
33
  useEffect(() => {
 
36
  }
37
  }, [meshRef]);
38
 
39
+ useImperativeHandle(ref, () => ({
40
+ resetPosition: () => {
41
+ meshRef.current?.position.set(x, y, z);
42
+ meshRef.current?.rotation.set(0, 0, 0);
43
+ },
44
+ }));
45
+
46
  const visibleFaces: Record<FacingDirection, boolean> = {
47
  front: z > 0,
48
  back: z < 0,
 
61
  };
62
 
63
  return (
64
+ <mesh position={[x, y, z]} ref={meshRef}>
65
  <RoundedBox args={[0.95, 0.95, 0.95]} radius={0.05} smoothness={4}>
66
  <meshStandardMaterial color="#2a2a2a" metalness={1} roughness={roughness} />
67
  </RoundedBox>
 
78
  })}
79
  </mesh>
80
  );
81
+ });
82
+
83
+ CubePiece.displayName = 'CubePiece';
src/components/rotation-controller.ts CHANGED
@@ -65,6 +65,16 @@ export class RotationController {
65
  return RotationController.instance;
66
  }
67
 
 
 
 
 
 
 
 
 
 
 
68
  setCubeGroup(cubeGroup: Group) {
69
  this.cubeGroup = cubeGroup;
70
  }
 
65
  return RotationController.instance;
66
  }
67
 
68
+ stopRotation(cb: () => void) {
69
+ this.rotationSteps = [];
70
+ const cancel = setInterval(() => {
71
+ if (!this.rotatingStep) {
72
+ clearInterval(cancel);
73
+ cb();
74
+ }
75
+ }, 50);
76
+ }
77
+
78
  setCubeGroup(cubeGroup: Group) {
79
  this.cubeGroup = cubeGroup;
80
  }
src/components/rubiks-cube.tsx CHANGED
@@ -2,7 +2,7 @@ import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
2
  import { Group } from 'three';
3
 
4
  import { RotationStep } from './consts';
5
- import { CubePiece } from './cube-piece';
6
  import { rotationController } from './rotation-controller';
7
  import { Rotator, RotatorRef } from './rotator';
8
 
@@ -17,6 +17,7 @@ for (let x = -0.5; x <= 0.5; x += 1) {
17
 
18
  export type RubiksCubeRef = {
19
  rotate: (steps: Array<RotationStep>) => void;
 
20
  };
21
 
22
  type RubiksCubeProps = {
@@ -27,9 +28,17 @@ type RubiksCubeProps = {
27
  export const RubiksCube = forwardRef<RubiksCubeRef, RubiksCubeProps>(({ cubeRoughness, cubeSpeed }, ref) => {
28
  const cubeGroupRef = useRef<Group | null>(null);
29
  const rotatorRef = useRef<RotatorRef | null>(null);
 
30
 
31
  useImperativeHandle(ref, () => ({
32
  rotate: (steps: Array<RotationStep>) => rotatorRef.current?.rotate(steps),
 
 
 
 
 
 
 
33
  }));
34
 
35
  useEffect(() => {
@@ -39,9 +48,23 @@ export const RubiksCube = forwardRef<RubiksCubeRef, RubiksCubeProps>(({ cubeRoug
39
  return (
40
  <>
41
  <group ref={cubeGroupRef}>
42
- {CUBE_POSITIONS.map((position) => (
43
- <CubePiece key={position.join(',')} initialPosition={position} roughness={cubeRoughness} />
44
- ))}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  </group>
46
  <Rotator ref={rotatorRef} cubeSpeed={cubeSpeed} />
47
  </>
 
2
  import { Group } from 'three';
3
 
4
  import { RotationStep } from './consts';
5
+ import { CubePiece, CubePieceRef } from './cube-piece';
6
  import { rotationController } from './rotation-controller';
7
  import { Rotator, RotatorRef } from './rotator';
8
 
 
17
 
18
  export type RubiksCubeRef = {
19
  rotate: (steps: Array<RotationStep>) => void;
20
+ reset: () => void;
21
  };
22
 
23
  type RubiksCubeProps = {
 
28
  export const RubiksCube = forwardRef<RubiksCubeRef, RubiksCubeProps>(({ cubeRoughness, cubeSpeed }, ref) => {
29
  const cubeGroupRef = useRef<Group | null>(null);
30
  const rotatorRef = useRef<RotatorRef | null>(null);
31
+ const cubePieceRefs = useRef<Map<string, CubePieceRef>>(new Map());
32
 
33
  useImperativeHandle(ref, () => ({
34
  rotate: (steps: Array<RotationStep>) => rotatorRef.current?.rotate(steps),
35
+ reset: () => {
36
+ rotationController.stopRotation(() => {
37
+ cubePieceRefs.current.forEach((cubePieceRef) => {
38
+ cubePieceRef.resetPosition();
39
+ });
40
+ });
41
+ },
42
  }));
43
 
44
  useEffect(() => {
 
48
  return (
49
  <>
50
  <group ref={cubeGroupRef}>
51
+ {CUBE_POSITIONS.map((position) => {
52
+ const positionKey = position.join(',');
53
+ return (
54
+ <CubePiece
55
+ key={positionKey}
56
+ ref={(ref) => {
57
+ if (ref) {
58
+ cubePieceRefs.current.set(positionKey, ref);
59
+ } else {
60
+ cubePieceRefs.current.delete(positionKey);
61
+ }
62
+ }}
63
+ initialPosition={position}
64
+ roughness={cubeRoughness}
65
+ />
66
+ );
67
+ })}
68
  </group>
69
  <Rotator ref={rotatorRef} cubeSpeed={cubeSpeed} />
70
  </>
src/components/ui-controls.tsx CHANGED
@@ -16,7 +16,7 @@ export const UIControls = () => {
16
  };
17
 
18
  const reset = () => {
19
- alert('Working on it!');
20
  };
21
 
22
  const solve = () => {
 
16
  };
17
 
18
  const reset = () => {
19
+ rubiksCubeRef?.current?.reset();
20
  };
21
 
22
  const solve = () => {
src/components/ui-title.tsx CHANGED
@@ -1,10 +1,14 @@
1
  export const UITitle = () => {
2
  return (
3
  <div className="z-10 pointer-events-none">
4
- <div className="text-6xl font-bold">Rubik&apos;s Cube Solver</div>
5
- <div className="text-2xl text-gray-800">with Reinforcement Learning</div>
6
- <div className="text-gray-700">
7
- <a href="https://cross-entropy.ai">https://cross-entropy.ai</a>
 
 
 
 
8
  </div>
9
  </div>
10
  );
 
1
  export const UITitle = () => {
2
  return (
3
  <div className="z-10 pointer-events-none">
4
+ <div className="pointer-events-auto w-fit">
5
+ <div className="text-6xl font-bold">Rubik&apos;s Cube Solver</div>
6
+ <div className="text-2xl text-gray-800">with Reinforcement Learning</div>
7
+ <div className="text-gray-700">
8
+ <a href="https://cross-entropy.ai" target="_blank" className="underline text-primary font-bold">
9
+ https://cross-entropy.ai
10
+ </a>
11
+ </div>
12
  </div>
13
  </div>
14
  );