imwithye commited on
Commit
9d0c4b5
·
1 Parent(s): 7cefe36

refactor code

Browse files
src/components/canvas.tsx CHANGED
@@ -29,7 +29,7 @@ export const Canvas = () => {
29
  { length: 20 },
30
  () => Actions[Math.floor(Math.random() * Actions.length)],
31
  );
32
- rubiksCubeRef.current?.scramble(scrambleSteps);
33
  }),
34
  });
35
 
 
29
  { length: 20 },
30
  () => Actions[Math.floor(Math.random() * Actions.length)],
31
  );
32
+ rubiksCubeRef.current?.rotate(scrambleSteps);
33
  }),
34
  });
35
 
src/components/consts.tsx CHANGED
@@ -6,6 +6,8 @@ export type FacingDirection =
6
  | "top"
7
  | "bottom";
8
 
 
 
9
  export const Rotations: Record<FacingDirection, [number, number, number]> = {
10
  front: [0, 0, 0],
11
  back: [0, Math.PI, 0],
@@ -15,10 +17,12 @@ export const Rotations: Record<FacingDirection, [number, number, number]> = {
15
  bottom: [Math.PI / 2, 0, 0],
16
  };
17
 
18
- export const Actions: Array<{
19
  faceDirection: FacingDirection;
20
- direction: "clockwise" | "counter-clockwise";
21
- }> = [
 
 
22
  { faceDirection: "front", direction: "clockwise" },
23
  { faceDirection: "front", direction: "counter-clockwise" },
24
  { faceDirection: "right", direction: "clockwise" },
 
6
  | "top"
7
  | "bottom";
8
 
9
+ export type RotationDirection = "clockwise" | "counter-clockwise";
10
+
11
  export const Rotations: Record<FacingDirection, [number, number, number]> = {
12
  front: [0, 0, 0],
13
  back: [0, Math.PI, 0],
 
17
  bottom: [Math.PI / 2, 0, 0],
18
  };
19
 
20
+ export type RotationStep = {
21
  faceDirection: FacingDirection;
22
+ direction: RotationDirection;
23
+ };
24
+
25
+ export const Actions: Array<RotationStep> = [
26
  { faceDirection: "front", direction: "clockwise" },
27
  { faceDirection: "front", direction: "counter-clockwise" },
28
  { faceDirection: "right", direction: "clockwise" },
src/components/rotation-panel.tsx CHANGED
@@ -2,21 +2,23 @@
2
 
3
  import { useLoader } from "@react-three/fiber";
4
  import { TextureLoader } from "three";
5
- import { Rotations, FacingDirection } from "./consts";
 
 
 
 
 
6
  import { useState } from "react";
7
 
8
  type RotationPanelProps = {
9
- direction: "clockwise" | "counter-clockwise";
10
  facingDirection: FacingDirection;
11
- onClick?: (
12
- facingDirection: FacingDirection,
13
- direction: "clockwise" | "counter-clockwise",
14
- ) => void;
15
  };
16
 
17
  export const RotationPanel = ({
18
- direction,
19
  facingDirection,
 
20
  onClick,
21
  }: RotationPanelProps) => {
22
  const clockwise = direction === "clockwise";
@@ -32,9 +34,8 @@ export const RotationPanel = ({
32
  bottom: clockwise ? [0.5, -1.01, 0] : [-0.5, -1.01, 0],
33
  };
34
 
35
- const handleClick = () => {
36
- onClick?.(facingDirection, direction);
37
- };
38
 
39
  return (
40
  <mesh
 
2
 
3
  import { useLoader } from "@react-three/fiber";
4
  import { TextureLoader } from "three";
5
+ import {
6
+ Rotations,
7
+ FacingDirection,
8
+ RotationStep,
9
+ RotationDirection,
10
+ } from "./consts";
11
  import { useState } from "react";
12
 
13
  type RotationPanelProps = {
 
14
  facingDirection: FacingDirection;
15
+ direction: RotationDirection;
16
+ onClick?: (step: RotationStep) => void;
 
 
17
  };
18
 
19
  export const RotationPanel = ({
 
20
  facingDirection,
21
+ direction,
22
  onClick,
23
  }: RotationPanelProps) => {
24
  const clockwise = direction === "clockwise";
 
34
  bottom: clockwise ? [0.5, -1.01, 0] : [-0.5, -1.01, 0],
35
  };
36
 
37
+ const handleClick = () =>
38
+ onClick?.({ faceDirection: facingDirection, direction });
 
39
 
40
  return (
41
  <mesh
src/components/rotator.tsx CHANGED
@@ -1,5 +1,5 @@
1
  import { useCubesContext } from "@/contexts/cubes-context";
2
- import { FacingDirection } from "./consts";
3
  import { RotationPanel } from "./rotation-panel";
4
  import { Group } from "three";
5
  import {
@@ -11,19 +11,8 @@ import {
11
  } from "react";
12
  import { useFrame } from "@react-three/fiber";
13
 
14
- type RotateArgs = {
15
- rotatingFaceDirection: FacingDirection;
16
- rotatingDirection: "clockwise" | "counter-clockwise";
17
- rotatingGroup: Group;
18
- };
19
-
20
  export type RotatorRef = {
21
- rotate: (
22
- steps: Array<{
23
- faceDirection: FacingDirection;
24
- direction: "clockwise" | "counter-clockwise";
25
- }>,
26
- ) => void;
27
  };
28
 
29
  type RotatorProps = {
@@ -32,108 +21,56 @@ type RotatorProps = {
32
 
33
  export const Rotator = forwardRef<RotatorRef, RotatorProps>(
34
  ({ cubeSpeed }: RotatorProps, ref) => {
 
 
35
  const { getCubes, cubeGroupRef } = useCubesContext();
36
- const rotationSteps = useRef<
37
- Array<{
38
- faceDirection: FacingDirection;
39
- direction: "clockwise" | "counter-clockwise";
40
- }>
41
- >([]);
42
 
43
  useImperativeHandle(ref, () => ({
44
- rotate: (
45
- steps: Array<{
46
- faceDirection: FacingDirection;
47
- direction: "clockwise" | "counter-clockwise";
48
- }>,
49
- ) => {
50
- steps.forEach((step) => {
51
- rotationSteps.current.push(step);
52
- });
53
- },
54
  }));
55
 
56
- const rotate = (
57
- rotatingFaceDirection: FacingDirection,
58
- rotatingDirection: "clockwise" | "counter-clockwise",
59
- rotatingGroup: Group,
60
- delta: number,
61
- ) => {
62
- let sign = 0;
63
- switch (rotatingFaceDirection) {
64
- case "front":
65
- sign = rotatingDirection === "clockwise" ? -1 : 1;
66
- rotatingGroup.rotation.z += sign * delta * cubeSpeed;
67
- if (Math.abs(rotatingGroup.rotation.z) > Math.PI / 2) {
68
- rotatingGroup.rotation.z = (Math.PI / 2) * sign;
69
- return true;
70
- }
71
- return false;
72
- case "back":
73
- sign = rotatingDirection === "clockwise" ? 1 : -1;
74
- rotatingGroup.rotation.z += sign * delta * cubeSpeed;
75
- if (Math.abs(rotatingGroup.rotation.z) > Math.PI / 2) {
76
- rotatingGroup.rotation.z = (Math.PI / 2) * sign;
77
- return true;
78
- }
79
- return false;
80
- case "left":
81
- sign = rotatingDirection === "clockwise" ? 1 : -1;
82
- rotatingGroup.rotation.x += sign * delta * cubeSpeed;
83
- if (Math.abs(rotatingGroup.rotation.x) > Math.PI / 2) {
84
- rotatingGroup.rotation.x = (Math.PI / 2) * sign;
85
- return true;
86
- }
87
- return false;
88
- case "right":
89
- sign = rotatingDirection === "clockwise" ? -1 : 1;
90
- rotatingGroup.rotation.x += sign * delta * cubeSpeed;
91
- if (Math.abs(rotatingGroup.rotation.x) > Math.PI / 2) {
92
- rotatingGroup.rotation.x = (Math.PI / 2) * sign;
93
- return true;
94
- }
95
- return false;
96
- case "top":
97
- sign = rotatingDirection === "clockwise" ? -1 : 1;
98
- rotatingGroup.rotation.y += sign * delta * cubeSpeed;
99
- if (Math.abs(rotatingGroup.rotation.y) > Math.PI / 2) {
100
- rotatingGroup.rotation.y = (Math.PI / 2) * sign;
101
- return true;
102
- }
103
- return false;
104
- case "bottom":
105
- sign = rotatingDirection === "clockwise" ? 1 : -1;
106
- rotatingGroup.rotation.y += sign * delta * cubeSpeed;
107
- if (Math.abs(rotatingGroup.rotation.y) > Math.PI / 2) {
108
- rotatingGroup.rotation.y = (Math.PI / 2) * sign;
109
- return true;
110
- }
111
- return false;
112
- }
113
- };
114
-
115
  const frameCallback = useMemo(() => {
116
- let rotationStep: {
117
- faceDirection: FacingDirection;
118
- direction: "clockwise" | "counter-clockwise";
119
- } | null = null;
120
  let rotatingGroup = new Group();
121
 
122
- const beforeRotationStep = (step: {
123
- faceDirection: FacingDirection;
124
- direction: "clockwise" | "counter-clockwise";
125
- }) => {
126
- const cubes = getCubes(step.faceDirection);
127
- rotationStep = step;
128
- rotatingGroup = new Group();
129
- cubeGroupRef.current?.add(rotatingGroup);
130
- cubes.forEach((cube) => rotatingGroup.attach(cube));
131
- };
132
- const afterRotationStep = () => {
133
- rotationStep = null;
134
- const children = [...rotatingGroup.children];
135
- children.forEach((child) => cubeGroupRef.current?.attach(child));
136
- cubeGroupRef.current?.remove(rotatingGroup);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  };
138
 
139
  return (state: unknown, delta: number) => {
@@ -142,28 +79,24 @@ export const Rotator = forwardRef<RotatorRef, RotatorProps>(
142
  if (!rotationStep) {
143
  const step = rotationSteps.current.shift();
144
  if (!step) return;
145
- beforeRotationStep(step);
 
 
 
 
146
  }
147
 
148
- const done = rotate(
149
- rotationStep?.faceDirection!,
150
- rotationStep?.direction!,
151
- rotatingGroup,
152
- delta,
153
- );
154
- if (done) afterRotationStep();
155
  };
156
- }, []);
157
-
158
  useFrame(frameCallback);
159
 
160
- const handleClick = (
161
- facingDirection: FacingDirection,
162
- direction: "clockwise" | "counter-clockwise",
163
- ) => {
164
- rotationSteps.current.push({ faceDirection: facingDirection, direction });
165
- };
166
-
167
  return (
168
  <>
169
  {["front", "back", "left", "right", "top", "bottom"].map(
@@ -172,12 +105,12 @@ export const Rotator = forwardRef<RotatorRef, RotatorProps>(
172
  <RotationPanel
173
  direction="clockwise"
174
  facingDirection={facingDirection as FacingDirection}
175
- onClick={handleClick}
176
  />
177
  <RotationPanel
178
  direction="counter-clockwise"
179
  facingDirection={facingDirection as FacingDirection}
180
- onClick={handleClick}
181
  />
182
  </Fragment>
183
  ),
 
1
  import { useCubesContext } from "@/contexts/cubes-context";
2
+ import { FacingDirection, RotationStep } from "./consts";
3
  import { RotationPanel } from "./rotation-panel";
4
  import { Group } from "three";
5
  import {
 
11
  } from "react";
12
  import { useFrame } from "@react-three/fiber";
13
 
 
 
 
 
 
 
14
  export type RotatorRef = {
15
+ rotate: (steps: Array<RotationStep>) => void;
 
 
 
 
 
16
  };
17
 
18
  type RotatorProps = {
 
21
 
22
  export const Rotator = forwardRef<RotatorRef, RotatorProps>(
23
  ({ cubeSpeed }: RotatorProps, ref) => {
24
+ const cubeSpeedRef = useRef(cubeSpeed);
25
+ cubeSpeedRef.current = cubeSpeed;
26
  const { getCubes, cubeGroupRef } = useCubesContext();
27
+ const rotationSteps = useRef<Array<RotationStep>>([]);
 
 
 
 
 
28
 
29
  useImperativeHandle(ref, () => ({
30
+ rotate: (steps: Array<RotationStep>) =>
31
+ rotationSteps.current.push(...steps),
 
 
 
 
 
 
 
 
32
  }));
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  const frameCallback = useMemo(() => {
35
+ let rotationStep: RotationStep | null = null;
 
 
 
36
  let rotatingGroup = new Group();
37
 
38
+ const rotate = (step: RotationStep, group: Group, delta: number) => {
39
+ let sign = 0;
40
+ let axis: "x" | "y" | "z" = "x";
41
+ switch (step.faceDirection) {
42
+ case "front":
43
+ sign = step.direction === "clockwise" ? -1 : 1;
44
+ axis = "z";
45
+ break;
46
+ case "back":
47
+ sign = step.direction === "clockwise" ? 1 : -1;
48
+ axis = "z";
49
+ break;
50
+ case "left":
51
+ sign = step.direction === "clockwise" ? 1 : -1;
52
+ axis = "x";
53
+ break;
54
+ case "right":
55
+ sign = step.direction === "clockwise" ? -1 : 1;
56
+ axis = "x";
57
+ break;
58
+ case "top":
59
+ sign = step.direction === "clockwise" ? -1 : 1;
60
+ axis = "y";
61
+ break;
62
+ case "bottom":
63
+ sign = step.direction === "clockwise" ? 1 : -1;
64
+ axis = "y";
65
+ break;
66
+ }
67
+
68
+ group.rotation[axis] += sign * delta * cubeSpeedRef.current;
69
+ if (Math.abs(group.rotation[axis]) > Math.PI / 2) {
70
+ group.rotation[axis] = (Math.PI / 2) * sign;
71
+ return true;
72
+ }
73
+ return false;
74
  };
75
 
76
  return (state: unknown, delta: number) => {
 
79
  if (!rotationStep) {
80
  const step = rotationSteps.current.shift();
81
  if (!step) return;
82
+ rotationStep = step;
83
+ const cubes = getCubes(step.faceDirection);
84
+ rotatingGroup = new Group();
85
+ cubeGroupRef.current?.add(rotatingGroup);
86
+ cubes.forEach((cube) => rotatingGroup.attach(cube));
87
  }
88
 
89
+ const done = rotate(rotationStep, rotatingGroup, delta);
90
+ if (done) {
91
+ rotationStep = null;
92
+ const children = [...rotatingGroup.children];
93
+ children.forEach((child) => cubeGroupRef.current?.attach(child));
94
+ cubeGroupRef.current?.remove(rotatingGroup);
95
+ }
96
  };
97
+ }, [cubeGroupRef, getCubes]);
 
98
  useFrame(frameCallback);
99
 
 
 
 
 
 
 
 
100
  return (
101
  <>
102
  {["front", "back", "left", "right", "top", "bottom"].map(
 
105
  <RotationPanel
106
  direction="clockwise"
107
  facingDirection={facingDirection as FacingDirection}
108
+ onClick={(s) => rotationSteps.current.push(s)}
109
  />
110
  <RotationPanel
111
  direction="counter-clockwise"
112
  facingDirection={facingDirection as FacingDirection}
113
+ onClick={(s) => rotationSteps.current.push(s)}
114
  />
115
  </Fragment>
116
  ),
src/components/rubiks-cube.tsx CHANGED
@@ -3,7 +3,7 @@ import { CubePiece } from "./cube-piece";
3
  import { Rotator, RotatorRef } from "./rotator";
4
  import { CubesProvider } from "@/contexts/cubes-context";
5
  import { Group } from "three";
6
- import { FacingDirection } from "./consts";
7
 
8
  const CUBE_POSITIONS: Array<[number, number, number]> = [];
9
  for (let x = -0.5; x <= 0.5; x += 1) {
@@ -15,12 +15,7 @@ for (let x = -0.5; x <= 0.5; x += 1) {
15
  }
16
 
17
  export type RubiksCubeRef = {
18
- scramble: (
19
- steps: Array<{
20
- faceDirection: FacingDirection;
21
- direction: "clockwise" | "counter-clockwise";
22
- }>,
23
- ) => void;
24
  };
25
 
26
  type RubiksCubeProps = {
@@ -34,12 +29,7 @@ export const RubiksCube = forwardRef<RubiksCubeRef, RubiksCubeProps>(
34
  const rotatorRef = useRef<RotatorRef | null>(null);
35
 
36
  useImperativeHandle(ref, () => ({
37
- scramble: (
38
- steps: Array<{
39
- faceDirection: FacingDirection;
40
- direction: "clockwise" | "counter-clockwise";
41
- }>,
42
- ) => rotatorRef.current?.rotate(steps),
43
  }));
44
 
45
  return (
 
3
  import { Rotator, RotatorRef } from "./rotator";
4
  import { CubesProvider } from "@/contexts/cubes-context";
5
  import { Group } from "three";
6
+ import { RotationStep } from "./consts";
7
 
8
  const CUBE_POSITIONS: Array<[number, number, number]> = [];
9
  for (let x = -0.5; x <= 0.5; x += 1) {
 
15
  }
16
 
17
  export type RubiksCubeRef = {
18
+ rotate: (steps: Array<RotationStep>) => void;
 
 
 
 
 
19
  };
20
 
21
  type RubiksCubeProps = {
 
29
  const rotatorRef = useRef<RotatorRef | null>(null);
30
 
31
  useImperativeHandle(ref, () => ({
32
+ rotate: (steps: Array<RotationStep>) => rotatorRef.current?.rotate(steps),
 
 
 
 
 
33
  }));
34
 
35
  return (