@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.
Files changed (51) hide show
  1. package/README.md +280 -170
  2. package/package.json +33 -3
  3. package/src/camera/cameraState.js +81 -0
  4. package/src/core.js +447 -0
  5. package/src/cube/animationSlice.js +205 -0
  6. package/src/cube/animationState.js +96 -0
  7. package/src/cube/cubeSettings.js +19 -0
  8. package/src/cube/cubeState.js +285 -139
  9. package/src/cube/stickerState.js +188 -0
  10. package/src/debouncer.js +16 -0
  11. package/src/globals.ts +9 -0
  12. package/src/index.js +621 -0
  13. package/src/settings.js +138 -0
  14. package/src/three/centerPiece.js +44 -0
  15. package/src/three/cornerPiece.js +60 -0
  16. package/src/three/cube.js +492 -0
  17. package/src/three/edgePiece.js +50 -0
  18. package/src/three/sticker.js +37 -0
  19. package/tests/common.js +27 -0
  20. package/tests/cube.five.test.js +126 -0
  21. package/tests/cube.four.test.js +126 -0
  22. package/tests/cube.seven.test.js +126 -0
  23. package/tests/cube.six.test.js +126 -0
  24. package/tests/cube.three.test.js +151 -0
  25. package/tests/cube.two.test.js +125 -0
  26. package/tests/setup.js +36 -0
  27. package/types/camera/cameraState.d.ts +19 -0
  28. package/types/core.d.ts +454 -0
  29. package/types/cube/animationSlice.d.ts +26 -0
  30. package/types/cube/animationState.d.ts +41 -0
  31. package/types/cube/cubeSettings.d.ts +17 -0
  32. package/types/cube/cubeState.d.ts +47 -0
  33. package/types/cube/stickerState.d.ts +21 -0
  34. package/types/debouncer.d.ts +13 -0
  35. package/types/globals.d.ts +7 -0
  36. package/types/index.d.ts +87 -0
  37. package/types/settings.d.ts +38 -0
  38. package/types/three/centerPiece.d.ts +15 -0
  39. package/types/three/cornerPiece.d.ts +24 -0
  40. package/types/three/cube.d.ts +130 -0
  41. package/types/three/edgePiece.d.ts +16 -0
  42. package/types/three/sticker.d.ts +15 -0
  43. package/.prettierrc +0 -7
  44. package/index.js +0 -274
  45. package/src/cube/cube.js +0 -276
  46. package/src/cube/cubeRotation.js +0 -63
  47. package/src/threejs/materials.js +0 -42
  48. package/src/threejs/pieces.js +0 -103
  49. package/src/threejs/stickers.js +0 -48
  50. package/src/utils/debouncer.js +0 -7
  51. 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
+ }
@@ -1,191 +1,337 @@
1
- import { Group } from 'three';
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
- * @typedef {{position: vector, rotation: vector, type: "corner" | "edge" | "center", group: Group}} state
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
- * @return {state[]}
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 corners = () => [
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 edges = () => [
71
- {
72
- position: { x: 1, y: 1, z: 0 },
73
- rotation: { x: 0, y: Math.PI / 2, z: 0 },
74
- type: 'edge',
75
- group: createEdgeGroup(Materials.right, Materials.up, Materials.core),
76
- },
77
- {
78
- position: { x: 1, y: 0, z: 1 },
79
- rotation: { x: 0, y: 0, z: -Math.PI / 2 },
80
- type: 'edge',
81
- group: createEdgeGroup(Materials.front, Materials.right, Materials.core),
82
- },
83
- {
84
- position: { x: 1, y: 0, z: -1 },
85
- rotation: { x: 0, y: Math.PI / 2, z: -Math.PI / 2 },
86
- type: 'edge',
87
- group: createEdgeGroup(Materials.right, Materials.back, Materials.core),
88
- },
89
- {
90
- position: { x: 1, y: -1, z: 0 },
91
- rotation: { x: Math.PI, y: Math.PI / 2, z: 0 },
92
- type: 'edge',
93
- group: createEdgeGroup(Materials.right, Materials.down, Materials.core),
94
- },
95
- {
96
- position: { x: 0, y: 1, z: 1 },
97
- rotation: { x: 0, y: 0, z: 0 },
98
- type: 'edge',
99
- group: createEdgeGroup(Materials.front, Materials.up, Materials.core),
100
- },
101
- {
102
- position: { x: 0, y: 1, z: -1 },
103
- rotation: { x: -Math.PI / 2, y: 0, z: 0 },
104
- type: 'edge',
105
- group: createEdgeGroup(Materials.up, Materials.back, Materials.core),
106
- },
107
- {
108
- position: { x: 0, y: -1, z: 1 },
109
- rotation: { x: Math.PI / 2, y: 0, z: 0 },
110
- type: 'edge',
111
- group: createEdgeGroup(Materials.down, Materials.front, Materials.core),
112
- },
113
- {
114
- position: { x: 0, y: -1, z: -1 },
115
- rotation: { x: Math.PI, y: 0, z: 0 },
116
- type: 'edge',
117
- group: createEdgeGroup(Materials.back, Materials.down, Materials.core),
118
- },
119
- {
120
- position: { x: -1, y: 1, z: 0 },
121
- rotation: { x: 0, y: -Math.PI / 2, z: 0 },
122
- type: 'edge',
123
- group: createEdgeGroup(Materials.left, Materials.up, Materials.core),
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 centers = () => [
149
- {
150
- position: { x: 1, y: 0, z: 0 },
151
- rotation: { x: 0, y: Math.PI / 2, z: 0 },
152
- type: 'center',
153
- group: createCenterGroup(Materials.right, Materials.core),
154
- },
155
- {
156
- position: { x: 0, y: 1, z: 0 },
157
- rotation: { x: -Math.PI / 2, y: 0, z: 0 },
158
- type: 'center',
159
- group: createCenterGroup(Materials.up, Materials.core),
160
- },
161
- {
162
- position: { x: 0, y: 0, z: 1 },
163
- rotation: { x: 0, y: 0, z: 0 },
164
- type: 'center',
165
- group: createCenterGroup(Materials.front, Materials.core),
166
- },
167
- {
168
- position: { x: 0, y: 0, z: -1 },
169
- rotation: { x: 0, y: Math.PI, z: 0 },
170
- type: 'center',
171
- group: createCenterGroup(Materials.back, Materials.core),
172
- },
173
- {
174
- position: { x: 0, y: -1, z: 0 },
175
- rotation: { x: Math.PI / 2, y: 0, z: 0 },
176
- type: 'center',
177
- group: createCenterGroup(Materials.down, Materials.core),
178
- },
179
- {
180
- position: { x: -1, y: 0, z: 0 },
181
- rotation: { x: 0, y: -Math.PI / 2, z: 0 },
182
- type: 'center',
183
- group: createCenterGroup(Materials.left, Materials.core),
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 };