Spaces:
Sleeping
Sleeping
get state
Browse files
src/components/consts.tsx
CHANGED
|
@@ -11,6 +11,15 @@ export const CubeColors: Record<FacingDirection, string> = {
|
|
| 11 |
bottom: '#ffffff', // White
|
| 12 |
};
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
export const Rotations: Record<FacingDirection, [number, number, number]> = {
|
| 15 |
front: [0, 0, 0],
|
| 16 |
back: [0, Math.PI, 0],
|
|
|
|
| 11 |
bottom: '#ffffff', // White
|
| 12 |
};
|
| 13 |
|
| 14 |
+
export const CubeColorIndices: Record<FacingDirection, number> = {
|
| 15 |
+
front: 0,
|
| 16 |
+
back: 1,
|
| 17 |
+
right: 2,
|
| 18 |
+
left: 3,
|
| 19 |
+
top: 4,
|
| 20 |
+
bottom: 5,
|
| 21 |
+
};
|
| 22 |
+
|
| 23 |
export const Rotations: Record<FacingDirection, [number, number, number]> = {
|
| 24 |
front: [0, 0, 0],
|
| 25 |
back: [0, Math.PI, 0],
|
src/components/cube-piece.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { RoundedBox } from '@react-three/drei';
|
|
| 4 |
import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
|
| 5 |
import { Mesh } from 'three';
|
| 6 |
|
| 7 |
-
import { CubeColors, FacingDirection, Rotations } from './consts';
|
| 8 |
import { rotationController } from './rotation-controller';
|
| 9 |
|
| 10 |
export type CubePieceRef = {
|
|
@@ -66,8 +66,8 @@ export const CubePiece = forwardRef<CubePieceRef, CubePieceProps>(({ roughness,
|
|
| 66 |
rotation={Rotations[face as FacingDirection]}
|
| 67 |
userData={{
|
| 68 |
isFace: true,
|
| 69 |
-
faceDirection: face,
|
| 70 |
faceColor: color,
|
|
|
|
| 71 |
}}
|
| 72 |
>
|
| 73 |
<planeGeometry args={[0.8, 0.8]} />
|
|
|
|
| 4 |
import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
|
| 5 |
import { Mesh } from 'three';
|
| 6 |
|
| 7 |
+
import { CubeColorIndices, CubeColors, FacingDirection, Rotations } from './consts';
|
| 8 |
import { rotationController } from './rotation-controller';
|
| 9 |
|
| 10 |
export type CubePieceRef = {
|
|
|
|
| 66 |
rotation={Rotations[face as FacingDirection]}
|
| 67 |
userData={{
|
| 68 |
isFace: true,
|
|
|
|
| 69 |
faceColor: color,
|
| 70 |
+
faceColorIndex: CubeColorIndices[face as FacingDirection],
|
| 71 |
}}
|
| 72 |
>
|
| 73 |
<planeGeometry args={[0.8, 0.8]} />
|
src/components/rotation-controller.ts
CHANGED
|
@@ -58,7 +58,7 @@ export class RotationController {
|
|
| 58 |
return false;
|
| 59 |
}
|
| 60 |
|
| 61 |
-
private
|
| 62 |
const faces = mesh.children.filter((child) => child.userData.isFace);
|
| 63 |
let axis: 'x' | 'y' | 'z' = 'x';
|
| 64 |
switch (faceDirection) {
|
|
@@ -86,8 +86,8 @@ export class RotationController {
|
|
| 86 |
maxFace = face as Mesh;
|
| 87 |
}
|
| 88 |
}
|
| 89 |
-
if (!maxFace) return
|
| 90 |
-
return maxFace;
|
| 91 |
}
|
| 92 |
|
| 93 |
static getInstance() {
|
|
@@ -123,10 +123,10 @@ export class RotationController {
|
|
| 123 |
return this.cubes.filter((m) => m.position.z > 0);
|
| 124 |
case 'back':
|
| 125 |
return this.cubes.filter((m) => m.position.z < 0);
|
| 126 |
-
case 'left':
|
| 127 |
-
return this.cubes.filter((m) => m.position.x < 0);
|
| 128 |
case 'right':
|
| 129 |
return this.cubes.filter((m) => m.position.x > 0);
|
|
|
|
|
|
|
| 130 |
case 'top':
|
| 131 |
return this.cubes.filter((m) => m.position.y > 0);
|
| 132 |
case 'bottom':
|
|
@@ -134,9 +134,13 @@ export class RotationController {
|
|
| 134 |
}
|
| 135 |
}
|
| 136 |
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
}
|
| 141 |
|
| 142 |
setCubeSpeed(cubeSpeed: number) {
|
|
|
|
| 58 |
return false;
|
| 59 |
}
|
| 60 |
|
| 61 |
+
private getCubeFaceColorIndex(mesh: Mesh, faceDirection: FacingDirection) {
|
| 62 |
const faces = mesh.children.filter((child) => child.userData.isFace);
|
| 63 |
let axis: 'x' | 'y' | 'z' = 'x';
|
| 64 |
switch (faceDirection) {
|
|
|
|
| 86 |
maxFace = face as Mesh;
|
| 87 |
}
|
| 88 |
}
|
| 89 |
+
if (!maxFace) return -1; // this should never happen
|
| 90 |
+
return maxFace.userData.faceColorIndex as number;
|
| 91 |
}
|
| 92 |
|
| 93 |
static getInstance() {
|
|
|
|
| 123 |
return this.cubes.filter((m) => m.position.z > 0);
|
| 124 |
case 'back':
|
| 125 |
return this.cubes.filter((m) => m.position.z < 0);
|
|
|
|
|
|
|
| 126 |
case 'right':
|
| 127 |
return this.cubes.filter((m) => m.position.x > 0);
|
| 128 |
+
case 'left':
|
| 129 |
+
return this.cubes.filter((m) => m.position.x < 0);
|
| 130 |
case 'top':
|
| 131 |
return this.cubes.filter((m) => m.position.y > 0);
|
| 132 |
case 'bottom':
|
|
|
|
| 134 |
}
|
| 135 |
}
|
| 136 |
|
| 137 |
+
getStatus() {
|
| 138 |
+
return ['front', 'back', 'right', 'left', 'top', 'bottom'].map((f) => {
|
| 139 |
+
const faceDirection = f as FacingDirection;
|
| 140 |
+
const cubes = this.getCubes(faceDirection);
|
| 141 |
+
const indices = cubes.map((cube) => this.getCubeFaceColorIndex(cube, faceDirection));
|
| 142 |
+
return indices;
|
| 143 |
+
});
|
| 144 |
}
|
| 145 |
|
| 146 |
setCubeSpeed(cubeSpeed: number) {
|
src/components/state-modal.tsx
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { Button, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, useDisclosure } from '@heroui/react';
|
| 4 |
+
import { forwardRef, useImperativeHandle, useState } from 'react';
|
| 5 |
+
|
| 6 |
+
export type StateModalRef = {
|
| 7 |
+
open: (status: Array<Array<number>>) => void;
|
| 8 |
+
};
|
| 9 |
+
|
| 10 |
+
export const StateModal = forwardRef<StateModalRef, unknown>((_, ref) => {
|
| 11 |
+
const [state, setState] = useState<Array<Array<number>>>([]);
|
| 12 |
+
const { isOpen, onOpen, onOpenChange } = useDisclosure();
|
| 13 |
+
|
| 14 |
+
useImperativeHandle(ref, () => ({
|
| 15 |
+
open: (state: Array<Array<number>>) => {
|
| 16 |
+
setState(state);
|
| 17 |
+
onOpen();
|
| 18 |
+
},
|
| 19 |
+
}));
|
| 20 |
+
|
| 21 |
+
const copy = () => {
|
| 22 |
+
navigator.clipboard.writeText(JSON.stringify(state));
|
| 23 |
+
};
|
| 24 |
+
|
| 25 |
+
return (
|
| 26 |
+
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
| 27 |
+
<ModalContent>
|
| 28 |
+
{(onClose) => (
|
| 29 |
+
<>
|
| 30 |
+
<ModalHeader>State</ModalHeader>
|
| 31 |
+
<ModalBody>
|
| 32 |
+
<div className="flex flex-col gap-2">
|
| 33 |
+
<div className="flex gap-2 items-center">
|
| 34 |
+
<div className="text-sm w-24 font-mont">Front</div>
|
| 35 |
+
<div className="font-mono">{JSON.stringify(state[0])}</div>
|
| 36 |
+
</div>
|
| 37 |
+
<div className="flex gap-2 items-center">
|
| 38 |
+
<div className="text-sm w-24 font-mont">Back</div>
|
| 39 |
+
<div className="font-mono">{JSON.stringify(state[1])}</div>
|
| 40 |
+
</div>
|
| 41 |
+
<div className="flex gap-2 items-center">
|
| 42 |
+
<div className="text-sm w-24 font-mont">Right</div>
|
| 43 |
+
<div className="font-mono">{JSON.stringify(state[2])}</div>
|
| 44 |
+
</div>
|
| 45 |
+
<div className="flex gap-2 items-center">
|
| 46 |
+
<div className="text-sm w-24 font-mont">Left</div>
|
| 47 |
+
<div className="font-mono">{JSON.stringify(state[3])}</div>
|
| 48 |
+
</div>
|
| 49 |
+
<div className="flex gap-2 items-center">
|
| 50 |
+
<div className="text-sm w-24 font-mont">Up</div>
|
| 51 |
+
<div className="font-mono">{JSON.stringify(state[4])}</div>
|
| 52 |
+
</div>
|
| 53 |
+
<div className="flex gap-2 items-center">
|
| 54 |
+
<div className="text-sm w-24 font-mont">Down</div>
|
| 55 |
+
<div className="font-mono">{JSON.stringify(state[5])}</div>
|
| 56 |
+
</div>
|
| 57 |
+
</div>
|
| 58 |
+
</ModalBody>
|
| 59 |
+
<ModalFooter>
|
| 60 |
+
<Button color="danger" variant="light" size="sm" onPress={onClose}>
|
| 61 |
+
Close
|
| 62 |
+
</Button>
|
| 63 |
+
<Button color="primary" size="sm" onPress={copy}>
|
| 64 |
+
Copy
|
| 65 |
+
</Button>
|
| 66 |
+
</ModalFooter>
|
| 67 |
+
</>
|
| 68 |
+
)}
|
| 69 |
+
</ModalContent>
|
| 70 |
+
</Modal>
|
| 71 |
+
);
|
| 72 |
+
});
|
| 73 |
+
|
| 74 |
+
StateModal.displayName = 'StateModal';
|
src/components/ui-controls.tsx
CHANGED
|
@@ -1,14 +1,16 @@
|
|
| 1 |
'use client';
|
| 2 |
|
| 3 |
import { Button, ButtonGroup, Card, CardBody, Checkbox, Slider } from '@heroui/react';
|
| 4 |
-
import { useState } from 'react';
|
| 5 |
|
| 6 |
import { useControlContext } from '@/contexts/control-context';
|
| 7 |
|
| 8 |
import { Actions } from './consts';
|
| 9 |
import { rotationController } from './rotation-controller';
|
|
|
|
| 10 |
|
| 11 |
export const UIControls = () => {
|
|
|
|
| 12 |
const [isControlsOpen, setIsControlsOpen] = useState(true);
|
| 13 |
const {
|
| 14 |
rubiksCubeRef,
|
|
@@ -31,8 +33,8 @@ export const UIControls = () => {
|
|
| 31 |
};
|
| 32 |
|
| 33 |
const showState = () => {
|
| 34 |
-
const
|
| 35 |
-
|
| 36 |
};
|
| 37 |
|
| 38 |
const solve = () => {
|
|
@@ -115,6 +117,8 @@ export const UIControls = () => {
|
|
| 115 |
</div>
|
| 116 |
</CardBody>
|
| 117 |
</Card>
|
|
|
|
|
|
|
| 118 |
</div>
|
| 119 |
);
|
| 120 |
};
|
|
|
|
| 1 |
'use client';
|
| 2 |
|
| 3 |
import { Button, ButtonGroup, Card, CardBody, Checkbox, Slider } from '@heroui/react';
|
| 4 |
+
import { useRef, useState } from 'react';
|
| 5 |
|
| 6 |
import { useControlContext } from '@/contexts/control-context';
|
| 7 |
|
| 8 |
import { Actions } from './consts';
|
| 9 |
import { rotationController } from './rotation-controller';
|
| 10 |
+
import { StateModal, StateModalRef } from './state-modal';
|
| 11 |
|
| 12 |
export const UIControls = () => {
|
| 13 |
+
const stateModalRef = useRef<StateModalRef | null>(null);
|
| 14 |
const [isControlsOpen, setIsControlsOpen] = useState(true);
|
| 15 |
const {
|
| 16 |
rubiksCubeRef,
|
|
|
|
| 33 |
};
|
| 34 |
|
| 35 |
const showState = () => {
|
| 36 |
+
const status = rotationController.getStatus();
|
| 37 |
+
stateModalRef.current?.open(status);
|
| 38 |
};
|
| 39 |
|
| 40 |
const solve = () => {
|
|
|
|
| 117 |
</div>
|
| 118 |
</CardBody>
|
| 119 |
</Card>
|
| 120 |
+
|
| 121 |
+
<StateModal ref={stateModalRef} />
|
| 122 |
</div>
|
| 123 |
);
|
| 124 |
};
|