@houstonp/rubiks-cube 1.5.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +280 -170
- package/package.json +33 -3
- package/src/camera/cameraState.js +81 -0
- package/src/core.js +447 -0
- package/src/cube/animationSlice.js +205 -0
- package/src/cube/animationState.js +96 -0
- package/src/cube/cubeSettings.js +19 -0
- package/src/cube/cubeState.js +285 -139
- package/src/cube/stickerState.js +188 -0
- package/src/debouncer.js +16 -0
- package/src/globals.ts +9 -0
- package/src/index.js +621 -0
- package/src/settings.js +138 -0
- package/src/three/centerPiece.js +44 -0
- package/src/three/cornerPiece.js +60 -0
- package/src/three/cube.js +492 -0
- package/src/three/edgePiece.js +50 -0
- package/src/three/sticker.js +37 -0
- package/tests/common.js +27 -0
- package/tests/cube.five.test.js +126 -0
- package/tests/cube.four.test.js +126 -0
- package/tests/cube.seven.test.js +126 -0
- package/tests/cube.six.test.js +126 -0
- package/tests/cube.three.test.js +151 -0
- package/tests/cube.two.test.js +125 -0
- package/tests/setup.js +36 -0
- package/types/camera/cameraState.d.ts +19 -0
- package/types/core.d.ts +454 -0
- package/types/cube/animationSlice.d.ts +26 -0
- package/types/cube/animationState.d.ts +41 -0
- package/types/cube/cubeSettings.d.ts +17 -0
- package/types/cube/cubeState.d.ts +47 -0
- package/types/cube/stickerState.d.ts +21 -0
- package/types/debouncer.d.ts +13 -0
- package/types/globals.d.ts +7 -0
- package/types/index.d.ts +87 -0
- package/types/settings.d.ts +38 -0
- package/types/three/centerPiece.d.ts +15 -0
- package/types/three/cornerPiece.d.ts +24 -0
- package/types/three/cube.d.ts +130 -0
- package/types/three/edgePiece.d.ts +16 -0
- package/types/three/sticker.d.ts +15 -0
- package/.prettierrc +0 -7
- package/index.js +0 -274
- package/src/cube/cube.js +0 -276
- package/src/cube/cubeRotation.js +0 -63
- package/src/threejs/materials.js +0 -42
- package/src/threejs/pieces.js +0 -103
- package/src/threejs/stickers.js +0 -48
- package/src/utils/debouncer.js +0 -7
- package/src/utils/rotation.js +0 -53
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/** @typedef {AnimationStatus[keyof AnimationStatus]} AnimationStatusType */
|
|
3
|
+
export const AnimationStatus = Object.freeze({
|
|
4
|
+
Pending: 'pending',
|
|
5
|
+
Initialised: 'initialised',
|
|
6
|
+
InProgress: 'inProgress',
|
|
7
|
+
Complete: 'complete',
|
|
8
|
+
Disposed: 'disposed',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export class AnimationState {
|
|
12
|
+
/**
|
|
13
|
+
* @param {import('./animationSlice').Slice} slice
|
|
14
|
+
* @param {((state: string) => void )} completedCallback
|
|
15
|
+
* @param {((reason: string) => void )} failedCallback
|
|
16
|
+
*/
|
|
17
|
+
constructor(slice, completedCallback, failedCallback) {
|
|
18
|
+
/** @type {((state: string) => void )} */
|
|
19
|
+
this.completedCallback = completedCallback;
|
|
20
|
+
/** @type {((reason: string) => void )} */
|
|
21
|
+
this.failedCallback = failedCallback;
|
|
22
|
+
/** @type {import('./animationSlice').Slice} */
|
|
23
|
+
this.slice = slice;
|
|
24
|
+
/** @type {AnimationStatusType} */
|
|
25
|
+
this.status = AnimationStatus.Pending;
|
|
26
|
+
/** @type {number} */
|
|
27
|
+
this.timestampMs = performance.now();
|
|
28
|
+
/** @type {number | undefined} */
|
|
29
|
+
this._lastUpdatedTimeMs = undefined;
|
|
30
|
+
/** @type {number} */
|
|
31
|
+
this._rotationPercentage = 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
initialise() {
|
|
35
|
+
this._lastUpdatedTimeMs = performance.now();
|
|
36
|
+
this.status = AnimationStatus.Initialised;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** @param {string} state */
|
|
40
|
+
complete(state) {
|
|
41
|
+
this.status = AnimationStatus.Disposed;
|
|
42
|
+
this.completedCallback(state);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** @param {string} reason */
|
|
46
|
+
abort(reason) {
|
|
47
|
+
this.status = AnimationStatus.Complete;
|
|
48
|
+
this.failedCallback(reason);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @param {number} speedMs
|
|
53
|
+
* @returns {number} rotationIncrement
|
|
54
|
+
*/
|
|
55
|
+
update(speedMs) {
|
|
56
|
+
if (speedMs < 0) {
|
|
57
|
+
throw new Error(`Speed is negative.`);
|
|
58
|
+
}
|
|
59
|
+
if (this.status === AnimationStatus.Initialised) {
|
|
60
|
+
this.status = AnimationStatus.InProgress;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (this.status !== AnimationStatus.InProgress) {
|
|
64
|
+
throw new Error(`Cannot update AnimationState. Invalid Status - [${this.status}]`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (this._lastUpdatedTimeMs == null) {
|
|
68
|
+
throw new Error(`Cannot update AnimationState. LastUpdated is not set. Value: "${this._lastUpdatedTimeMs}".`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
var intervalMs = performance.now() - this._lastUpdatedTimeMs;
|
|
72
|
+
this._lastUpdatedTimeMs = performance.now();
|
|
73
|
+
|
|
74
|
+
var increment = 100 - this._rotationPercentage;
|
|
75
|
+
if (speedMs != 0) {
|
|
76
|
+
var potentialIncrement = (intervalMs / speedMs) * 100;
|
|
77
|
+
if (potentialIncrement + this._rotationPercentage < 100) {
|
|
78
|
+
increment = potentialIncrement;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (this._rotationPercentage + increment > 100) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`Cannot update AnimationState. Next increment would cause over rotation. Increment: ${increment}%. Current rotation: ${this._rotationPercentage}%.`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this._rotationPercentage += increment;
|
|
89
|
+
|
|
90
|
+
if (this._rotationPercentage === 100) {
|
|
91
|
+
this.status = AnimationStatus.Complete;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return increment;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
export default class CubeSettings {
|
|
3
|
+
/**
|
|
4
|
+
* @param {import('../core').CubeType} cubeType
|
|
5
|
+
* @param {number} pieceGap
|
|
6
|
+
* @param {number} animationSpeed
|
|
7
|
+
* @param {import('../core').AnimationStyle} animationStyle
|
|
8
|
+
*/
|
|
9
|
+
constructor(pieceGap, animationSpeed, animationStyle, cubeType) {
|
|
10
|
+
/** @type {number} pieceGap */
|
|
11
|
+
this.pieceGap = pieceGap;
|
|
12
|
+
/** @type {import("../core").CubeType} */
|
|
13
|
+
this.cubeType = cubeType;
|
|
14
|
+
/** @type {number} pieceGap */
|
|
15
|
+
this.animationSpeedMs = animationSpeed;
|
|
16
|
+
/** @type {import('../core').AnimationStyle} pieceGap */
|
|
17
|
+
this.animationStyle = animationStyle;
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/cube/cubeState.js
CHANGED
|
@@ -1,191 +1,337 @@
|
|
|
1
|
-
|
|
2
|
-
import Materials from '../threejs/materials';
|
|
3
|
-
import { createCornerGroup, createEdgeGroup, createCenterGroup } from '../threejs/pieces';
|
|
4
|
-
|
|
1
|
+
// @ts-check
|
|
5
2
|
/**
|
|
6
3
|
* @typedef {{x: number,y: number,z: number}} vector
|
|
7
4
|
*/
|
|
8
5
|
|
|
6
|
+
import { CubeTypes, Faces } from '../core';
|
|
7
|
+
import { defaultStickerState } from './stickerState';
|
|
8
|
+
|
|
9
|
+
/** @typedef {{cubeType: import('../core').CubeType, layers: number[], pieceSize: number, coreSize: number,initialStickerState: import('./stickerState').StickerState, outerLayerMultiplier: number, corners: state[], edges: state[], centers: state[]}} CubeInfo */
|
|
9
10
|
/**
|
|
10
|
-
* @
|
|
11
|
+
* @param {import("../core").CubeType} cubeType
|
|
12
|
+
* @return {CubeInfo}
|
|
11
13
|
*/
|
|
14
|
+
export function getCubeInfo(cubeType) {
|
|
15
|
+
return {
|
|
16
|
+
cubeType: cubeType,
|
|
17
|
+
layers: getMiddleLayers(cubeType),
|
|
18
|
+
pieceSize: pieceSize(cubeType),
|
|
19
|
+
coreSize: coreSize(cubeType),
|
|
20
|
+
initialStickerState: defaultStickerState(cubeType),
|
|
21
|
+
outerLayerMultiplier: outlerLayerMultiplier(cubeType),
|
|
22
|
+
corners: corners,
|
|
23
|
+
edges: edges(getMiddleLayers(cubeType)),
|
|
24
|
+
centers: centers(getMiddleLayers(cubeType)),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const FaceColors = {
|
|
29
|
+
[Faces.B]: 'blue',
|
|
30
|
+
[Faces.D]: 'yellow',
|
|
31
|
+
[Faces.F]: '#2cbf13',
|
|
32
|
+
[Faces.L]: '#fc9a05',
|
|
33
|
+
[Faces.R]: 'red',
|
|
34
|
+
[Faces.U]: 'white',
|
|
35
|
+
};
|
|
12
36
|
|
|
13
37
|
/**
|
|
14
|
-
* @
|
|
38
|
+
* @param {import('three').ColorRepresentation} color
|
|
39
|
+
* @return {import('../core').Face}
|
|
40
|
+
* */
|
|
41
|
+
export const ColorToFace = (color) => {
|
|
42
|
+
const face = Object.values(Faces).find((face) => FaceColors[face] === color);
|
|
43
|
+
if (!face) {
|
|
44
|
+
throw new Error(`Invalid color: ${color}`);
|
|
45
|
+
}
|
|
46
|
+
return face;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {import("../core").CubeType} cubeType
|
|
51
|
+
* @return {number} core size
|
|
52
|
+
*/
|
|
53
|
+
export const outlerLayerMultiplier = (cubeType) => {
|
|
54
|
+
switch (cubeType) {
|
|
55
|
+
case CubeTypes.Two:
|
|
56
|
+
return 1;
|
|
57
|
+
case CubeTypes.Three:
|
|
58
|
+
return 1;
|
|
59
|
+
case CubeTypes.Four:
|
|
60
|
+
return 1.1;
|
|
61
|
+
case CubeTypes.Five:
|
|
62
|
+
return 1.2;
|
|
63
|
+
case CubeTypes.Six:
|
|
64
|
+
return 1.3;
|
|
65
|
+
case CubeTypes.Seven:
|
|
66
|
+
return 1.35;
|
|
67
|
+
default:
|
|
68
|
+
throw new Error(`Unsupported cube type: ${cubeType}`);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @param {import("../core").CubeType} cubeType
|
|
74
|
+
* @return {number} core size
|
|
75
|
+
*/
|
|
76
|
+
export const coreSize = (cubeType) => {
|
|
77
|
+
switch (cubeType) {
|
|
78
|
+
case CubeTypes.Two:
|
|
79
|
+
return 2;
|
|
80
|
+
case CubeTypes.Three:
|
|
81
|
+
return 1.53;
|
|
82
|
+
case CubeTypes.Four:
|
|
83
|
+
return 1.36;
|
|
84
|
+
case CubeTypes.Five:
|
|
85
|
+
return 1.3;
|
|
86
|
+
case CubeTypes.Six:
|
|
87
|
+
return 1.22;
|
|
88
|
+
case CubeTypes.Seven:
|
|
89
|
+
return 1.21;
|
|
90
|
+
default:
|
|
91
|
+
throw new Error(`Unsupported cube type: ${cubeType}`);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @param {import("../core").CubeType} cubeType
|
|
97
|
+
*/
|
|
98
|
+
export const getMiddleLayers = (cubeType) => {
|
|
99
|
+
switch (cubeType) {
|
|
100
|
+
case CubeTypes.Two:
|
|
101
|
+
return [];
|
|
102
|
+
case CubeTypes.Three:
|
|
103
|
+
return [0];
|
|
104
|
+
case CubeTypes.Four:
|
|
105
|
+
return [-1 / 3, 1 / 3];
|
|
106
|
+
case CubeTypes.Five:
|
|
107
|
+
return [-1 / 2, 0, 1 / 2];
|
|
108
|
+
case CubeTypes.Six:
|
|
109
|
+
return [-3 / 5, -1 / 5, 1 / 5, 3 / 5];
|
|
110
|
+
case CubeTypes.Seven:
|
|
111
|
+
return [-2 / 3, -1 / 3, 0, 1 / 3, 2 / 3];
|
|
112
|
+
default:
|
|
113
|
+
throw new Error(`Unsupported cube type: ${cubeType}`);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @param {import("../core").CubeType} cubeType
|
|
119
|
+
*/
|
|
120
|
+
export const getAllLayers = (cubeType) => {
|
|
121
|
+
return [-1, ...getMiddleLayers(cubeType), 1];
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @param {import("../core").CubeType} cubeType
|
|
126
|
+
* @return {number} piece size
|
|
15
127
|
*/
|
|
16
|
-
const
|
|
128
|
+
export const pieceSize = (cubeType) => {
|
|
129
|
+
switch (cubeType) {
|
|
130
|
+
case CubeTypes.Two:
|
|
131
|
+
return 2;
|
|
132
|
+
case CubeTypes.Three:
|
|
133
|
+
return 1;
|
|
134
|
+
case CubeTypes.Four:
|
|
135
|
+
return 2 / 3;
|
|
136
|
+
case CubeTypes.Five:
|
|
137
|
+
return 1 / 2;
|
|
138
|
+
case CubeTypes.Six:
|
|
139
|
+
return 2 / 5;
|
|
140
|
+
case CubeTypes.Seven:
|
|
141
|
+
return 1 / 3;
|
|
142
|
+
default:
|
|
143
|
+
throw new Error(`Unsupported cube type: ${cubeType}`);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @typedef {{position: vector, rotation: vector}} state
|
|
149
|
+
*/
|
|
150
|
+
|
|
151
|
+
/** @type {state[]} */
|
|
152
|
+
export const corners = [
|
|
17
153
|
{
|
|
18
154
|
position: { x: 1, y: 1, z: 1 },
|
|
19
155
|
rotation: { x: 0, y: 0, z: 0 },
|
|
20
|
-
type: 'corner',
|
|
21
|
-
group: createCornerGroup(Materials.front, Materials.right, Materials.up, Materials.core),
|
|
22
156
|
},
|
|
23
157
|
{
|
|
24
158
|
position: { x: 1, y: 1, z: -1 },
|
|
25
159
|
rotation: { x: 0, y: Math.PI / 2, z: 0 },
|
|
26
|
-
type: 'corner',
|
|
27
|
-
group: createCornerGroup(Materials.right, Materials.back, Materials.up, Materials.core),
|
|
28
160
|
},
|
|
29
161
|
{
|
|
30
162
|
position: { x: 1, y: -1, z: 1 },
|
|
31
163
|
rotation: { x: 0, y: Math.PI / 2, z: Math.PI },
|
|
32
|
-
type: 'corner',
|
|
33
|
-
group: createCornerGroup(Materials.right, Materials.front, Materials.down, Materials.core),
|
|
34
164
|
},
|
|
35
165
|
{
|
|
36
166
|
position: { x: 1, y: -1, z: -1 },
|
|
37
167
|
rotation: { x: 0, y: Math.PI, z: Math.PI },
|
|
38
|
-
type: 'corner',
|
|
39
|
-
group: createCornerGroup(Materials.back, Materials.right, Materials.down, Materials.core),
|
|
40
168
|
},
|
|
41
169
|
{
|
|
42
170
|
position: { x: -1, y: 1, z: 1 },
|
|
43
171
|
rotation: { x: 0, y: -Math.PI / 2, z: 0 },
|
|
44
|
-
type: 'corner',
|
|
45
|
-
group: createCornerGroup(Materials.left, Materials.front, Materials.up, Materials.core),
|
|
46
172
|
},
|
|
47
173
|
{
|
|
48
174
|
position: { x: -1, y: 1, z: -1 },
|
|
49
175
|
rotation: { x: 0, y: Math.PI, z: 0 },
|
|
50
|
-
type: 'corner',
|
|
51
|
-
group: createCornerGroup(Materials.back, Materials.left, Materials.up, Materials.core),
|
|
52
176
|
},
|
|
53
177
|
{
|
|
54
178
|
position: { x: -1, y: -1, z: 1 },
|
|
55
179
|
rotation: { x: 0, y: 0, z: Math.PI },
|
|
56
|
-
type: 'corner',
|
|
57
|
-
group: createCornerGroup(Materials.front, Materials.left, Materials.down, Materials.core),
|
|
58
180
|
},
|
|
59
181
|
{
|
|
60
182
|
position: { x: -1, y: -1, z: -1 },
|
|
61
183
|
rotation: { x: 0, y: -Math.PI / 2, z: Math.PI },
|
|
62
|
-
type: 'corner',
|
|
63
|
-
group: createCornerGroup(Materials.left, Materials.back, Materials.down, Materials.core),
|
|
64
184
|
},
|
|
65
185
|
];
|
|
66
186
|
|
|
67
187
|
/**
|
|
188
|
+
* @param {number[]} layers
|
|
68
189
|
* @return {state[]}
|
|
69
190
|
*/
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
{
|
|
126
|
-
position: { x: -1, y: 0, z: 1 },
|
|
127
|
-
rotation: { x: 0, y: 0, z: Math.PI / 2 },
|
|
128
|
-
type: 'edge',
|
|
129
|
-
group: createEdgeGroup(Materials.front, Materials.left, Materials.core),
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
position: { x: -1, y: 0, z: -1 },
|
|
133
|
-
rotation: { x: 0, y: -Math.PI / 2, z: Math.PI / 2 },
|
|
134
|
-
type: 'edge',
|
|
135
|
-
group: createEdgeGroup(Materials.left, Materials.back, Materials.core),
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
position: { x: -1, y: -1, z: 0 },
|
|
139
|
-
rotation: { x: 0, y: -Math.PI / 2, z: Math.PI },
|
|
140
|
-
type: 'edge',
|
|
141
|
-
group: createEdgeGroup(Materials.left, Materials.down, Materials.core),
|
|
142
|
-
},
|
|
191
|
+
export const centers = (layers) => [
|
|
192
|
+
//right
|
|
193
|
+
...layers.flatMap((layer1) =>
|
|
194
|
+
layers.map((layer2) => {
|
|
195
|
+
return {
|
|
196
|
+
position: { x: 1, y: layer1, z: layer2 },
|
|
197
|
+
rotation: { x: 0, y: Math.PI / 2, z: 0 },
|
|
198
|
+
};
|
|
199
|
+
}),
|
|
200
|
+
),
|
|
201
|
+
//up
|
|
202
|
+
...layers.flatMap((layer1) =>
|
|
203
|
+
layers.map((layer2) => {
|
|
204
|
+
return {
|
|
205
|
+
position: { x: layer1, y: 1, z: layer2 },
|
|
206
|
+
rotation: { x: -Math.PI / 2, y: 0, z: 0 },
|
|
207
|
+
};
|
|
208
|
+
}),
|
|
209
|
+
),
|
|
210
|
+
//front
|
|
211
|
+
...layers.flatMap((layer1) =>
|
|
212
|
+
layers.map((layer2) => {
|
|
213
|
+
return {
|
|
214
|
+
position: { x: layer1, y: layer2, z: 1 },
|
|
215
|
+
rotation: { x: 0, y: 0, z: 0 },
|
|
216
|
+
};
|
|
217
|
+
}),
|
|
218
|
+
),
|
|
219
|
+
//back
|
|
220
|
+
...layers.flatMap((layer1) =>
|
|
221
|
+
layers.map((layer2) => {
|
|
222
|
+
return {
|
|
223
|
+
position: { x: layer1, y: layer2, z: -1 },
|
|
224
|
+
rotation: { x: 0, y: Math.PI, z: 0 },
|
|
225
|
+
};
|
|
226
|
+
}),
|
|
227
|
+
),
|
|
228
|
+
//down
|
|
229
|
+
...layers.flatMap((layer1) =>
|
|
230
|
+
layers.map((layer2) => {
|
|
231
|
+
return {
|
|
232
|
+
position: { x: layer1, y: -1, z: layer2 },
|
|
233
|
+
rotation: { x: Math.PI / 2, y: 0, z: 0 },
|
|
234
|
+
};
|
|
235
|
+
}),
|
|
236
|
+
),
|
|
237
|
+
//left
|
|
238
|
+
...layers.flatMap((layer1) =>
|
|
239
|
+
layers.map((layer2) => {
|
|
240
|
+
return {
|
|
241
|
+
position: { x: -1, y: layer1, z: layer2 },
|
|
242
|
+
rotation: { x: 0, y: -Math.PI / 2, z: 0 },
|
|
243
|
+
};
|
|
244
|
+
}),
|
|
245
|
+
),
|
|
143
246
|
];
|
|
144
247
|
|
|
145
248
|
/**
|
|
249
|
+
* @param {number[]} layers
|
|
146
250
|
* @return {state[]}
|
|
147
251
|
*/
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
252
|
+
export const edges = (layers) => [
|
|
253
|
+
// RU
|
|
254
|
+
...layers.map((layer) => {
|
|
255
|
+
return {
|
|
256
|
+
position: { x: 1, y: 1, z: layer },
|
|
257
|
+
rotation: { x: 0, y: Math.PI / 2, z: 0 },
|
|
258
|
+
};
|
|
259
|
+
}),
|
|
260
|
+
// RF
|
|
261
|
+
...layers.map((layer) => {
|
|
262
|
+
return {
|
|
263
|
+
position: { x: 1, y: layer, z: 1 },
|
|
264
|
+
rotation: { x: 0, y: 0, z: -Math.PI / 2 },
|
|
265
|
+
};
|
|
266
|
+
}),
|
|
267
|
+
// RB
|
|
268
|
+
...layers.map((layer) => {
|
|
269
|
+
return {
|
|
270
|
+
position: { x: 1, y: layer, z: -1 },
|
|
271
|
+
rotation: { x: 0, y: Math.PI / 2, z: -Math.PI / 2 },
|
|
272
|
+
};
|
|
273
|
+
}),
|
|
274
|
+
// RD
|
|
275
|
+
...layers.map((layer) => {
|
|
276
|
+
return {
|
|
277
|
+
position: { x: 1, y: -1, z: layer },
|
|
278
|
+
rotation: { x: Math.PI, y: Math.PI / 2, z: 0 },
|
|
279
|
+
};
|
|
280
|
+
}),
|
|
281
|
+
// UF
|
|
282
|
+
...layers.map((layer) => {
|
|
283
|
+
return {
|
|
284
|
+
position: { x: layer, y: 1, z: 1 },
|
|
285
|
+
rotation: { x: 0, y: 0, z: 0 },
|
|
286
|
+
};
|
|
287
|
+
}),
|
|
288
|
+
// UB
|
|
289
|
+
...layers.map((layer) => {
|
|
290
|
+
return {
|
|
291
|
+
position: { x: layer, y: 1, z: -1 },
|
|
292
|
+
rotation: { x: -Math.PI / 2, y: 0, z: 0 },
|
|
293
|
+
};
|
|
294
|
+
}),
|
|
295
|
+
// DF
|
|
296
|
+
...layers.map((layer) => {
|
|
297
|
+
return {
|
|
298
|
+
position: { x: layer, y: -1, z: 1 },
|
|
299
|
+
rotation: { x: Math.PI / 2, y: 0, z: 0 },
|
|
300
|
+
};
|
|
301
|
+
}),
|
|
302
|
+
// DB
|
|
303
|
+
...layers.map((layer) => {
|
|
304
|
+
return {
|
|
305
|
+
position: { x: layer, y: -1, z: -1 },
|
|
306
|
+
rotation: { x: Math.PI, y: 0, z: 0 },
|
|
307
|
+
};
|
|
308
|
+
}),
|
|
309
|
+
// LU
|
|
310
|
+
...layers.map((layer) => {
|
|
311
|
+
return {
|
|
312
|
+
position: { x: -1, y: 1, z: layer },
|
|
313
|
+
rotation: { x: 0, y: -Math.PI / 2, z: 0 },
|
|
314
|
+
};
|
|
315
|
+
}),
|
|
316
|
+
// LF
|
|
317
|
+
...layers.map((layer) => {
|
|
318
|
+
return {
|
|
319
|
+
position: { x: -1, y: layer, z: 1 },
|
|
320
|
+
rotation: { x: 0, y: 0, z: Math.PI / 2 },
|
|
321
|
+
};
|
|
322
|
+
}),
|
|
323
|
+
// LB
|
|
324
|
+
...layers.map((layer) => {
|
|
325
|
+
return {
|
|
326
|
+
position: { x: -1, y: layer, z: -1 },
|
|
327
|
+
rotation: { x: 0, y: -Math.PI / 2, z: Math.PI / 2 },
|
|
328
|
+
};
|
|
329
|
+
}),
|
|
330
|
+
// LD
|
|
331
|
+
...layers.map((layer) => {
|
|
332
|
+
return {
|
|
333
|
+
position: { x: -1, y: -1, z: layer },
|
|
334
|
+
rotation: { x: 0, y: -Math.PI / 2, z: Math.PI },
|
|
335
|
+
};
|
|
336
|
+
}),
|
|
185
337
|
];
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* @return {state[]}
|
|
189
|
-
*/
|
|
190
|
-
const createCubeState = () => [...corners(), ...edges(), ...centers()];
|
|
191
|
-
export { createCubeState };
|