cube-state-engine 1.0.5 → 1.2.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/.idea/cube-state-engine.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +36 -15
- package/dist/index.d.mts +346 -0
- package/dist/index.d.ts +346 -0
- package/dist/index.js +316 -2
- package/dist/index.mjs +316 -2
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="WEB_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager">
|
|
4
|
+
<content url="file://$MODULE_DIR$">
|
|
5
|
+
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
6
|
+
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
7
|
+
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
8
|
+
</content>
|
|
9
|
+
<orderEntry type="inheritedJdk" />
|
|
10
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
11
|
+
</component>
|
|
12
|
+
</module>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ProjectModuleManager">
|
|
4
|
+
<modules>
|
|
5
|
+
<module fileurl="file://$PROJECT_DIR$/.idea/cube-state-engine.iml" filepath="$PROJECT_DIR$/.idea/cube-state-engine.iml" />
|
|
6
|
+
</modules>
|
|
7
|
+
</component>
|
|
8
|
+
</project>
|
package/.idea/vcs.xml
ADDED
package/README.md
CHANGED
|
@@ -12,18 +12,27 @@ A core state manager designed to integrate with custom 3D cube models. This engi
|
|
|
12
12
|
|
|
13
13
|
## Methods
|
|
14
14
|
|
|
15
|
-
| Method
|
|
16
|
-
|
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
25
|
-
| `rotateL(clockwise
|
|
26
|
-
| `rotateR(clockwise
|
|
15
|
+
| Method | Description | Return Type |
|
|
16
|
+
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------- |---------------------|
|
|
17
|
+
| `constructor(initialScramble?: string)` | Optionally initialize the cube with a scramble string (not recorded in history). | `CubeEngine` |
|
|
18
|
+
| `isSolved()` | Checks if the cube is solved. | `boolean` |
|
|
19
|
+
| `state()` | Returns the current state of the cube as an object representing each face. | `object` |
|
|
20
|
+
| `getMoves(asString?: boolean)` | Returns the history of all movements; as string if `true` (default), or as array if `false`. | `string / string[]` |
|
|
21
|
+
| `reset()` | Resets the cube to the solved state and clears the move history. | `void` |
|
|
22
|
+
| `applyMoves(sequence: string, options?: {record?: boolean})` | Applies a sequence of moves (supports U, D, L, R, F, x, y, z, M, Dw, Uw, Rw, Lw with ', 2). | `void` |
|
|
23
|
+
| `rotateU(clockwise?: boolean)` | Rotates the **Upper** layer clockwise or counterclockwise. | `void` |
|
|
24
|
+
| `rotateD(clockwise?: boolean)` | Rotates the **Down** layer clockwise or counterclockwise. | `void` |
|
|
25
|
+
| `rotateL(clockwise?: boolean)` | Rotates the **Left** layer clockwise or counterclockwise. | `void` |
|
|
26
|
+
| `rotateR(clockwise?: boolean)` | Rotates the **Right** layer clockwise or counterclockwise. | `void` |
|
|
27
|
+
| `rotateF(clockwise?: boolean)` | Rotates the **Front** layer clockwise or counterclockwise. | `void` |
|
|
28
|
+
| `rotateX(clockwise?: boolean)` | Rotates the cube along the **X-axis** clockwise or counterclockwise. | `void` |
|
|
29
|
+
| `rotateY(clockwise?: boolean)` | Rotates the cube along the **Y-axis** clockwise or counterclockwise. | `void` |
|
|
30
|
+
| `rotateZ(clockwise?: boolean)` | Rotates the cube along the **Z-axis** clockwise or counterclockwise. | `void` |
|
|
31
|
+
| `rotateDw(clockwise?: boolean)` | Rotates the wide **Down** two layers. | `void` |
|
|
32
|
+
| `rotateUw(clockwise?: boolean)` | Rotates the wide **Upper** two layers. | `void` |
|
|
33
|
+
| `rotateRw(clockwise?: boolean)` | Rotates the wide **Right** two layers. | `void` |
|
|
34
|
+
| `rotateLw(clockwise?: boolean)` | Rotates the wide **Left** two layers. | `void` |
|
|
35
|
+
| `rotateM(clockwise?: boolean)` | Rotates the middle slice parallel to L/R. | `void` |
|
|
27
36
|
|
|
28
37
|
---
|
|
29
38
|
|
|
@@ -47,18 +56,30 @@ The `state()` method returns the current state of the cube as an object with six
|
|
|
47
56
|
```javascript
|
|
48
57
|
import { CubeEngine } from "cube-state-engine";
|
|
49
58
|
|
|
50
|
-
// Initialize the engine
|
|
51
|
-
const cube = new CubeEngine();
|
|
59
|
+
// Initialize the engine (optionally with a scramble)
|
|
60
|
+
const cube = new CubeEngine("R U' F R2 D");
|
|
52
61
|
|
|
53
62
|
// Check if the cube is solved
|
|
54
|
-
console.log(cube.isSolved());
|
|
63
|
+
console.log(cube.isSolved());
|
|
55
64
|
|
|
56
65
|
// Rotate the upper face clockwise
|
|
57
66
|
cube.rotateU(true);
|
|
58
67
|
|
|
68
|
+
// Apply an algorithm and record moves
|
|
69
|
+
cube.applyMoves("Dw Dw' M2", { record: true });
|
|
70
|
+
|
|
59
71
|
// Get the current cube state
|
|
60
72
|
console.log(cube.state());
|
|
61
73
|
|
|
74
|
+
// Get history as string or array
|
|
75
|
+
console.log(cube.getMoves(true)); // "U Dw Dw' M2 ..."
|
|
76
|
+
console.log(cube.getMoves(false)); // ["U", "Dw", "Dw'", "M", "M"]
|
|
77
|
+
|
|
78
|
+
// Reset the cube to solved state and clear history
|
|
79
|
+
cube.reset();
|
|
80
|
+
console.log(cube.isSolved()); // true
|
|
81
|
+
console.log(cube.getMoves(false)); // []
|
|
82
|
+
|
|
62
83
|
// Rotate the cube along the Y-axis
|
|
63
84
|
cube.rotateY(false);
|
|
64
85
|
```
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
class CubeEngine {
|
|
2
2
|
MOVES = [];
|
|
3
3
|
|
|
4
|
+
constructor(initialScramble = "") {
|
|
5
|
+
// If an initial scramble string is provided, apply it without recording moves
|
|
6
|
+
if (typeof initialScramble === "string" && initialScramble.trim().length > 0) {
|
|
7
|
+
this.#applyMovesFromString(initialScramble, false);
|
|
8
|
+
// Ensure history is empty for initial position
|
|
9
|
+
this.MOVES = [];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
4
13
|
// States object for the rotation
|
|
5
14
|
STATES = {
|
|
6
15
|
UPPER: [
|
|
@@ -190,6 +199,122 @@ class CubeEngine {
|
|
|
190
199
|
}
|
|
191
200
|
}
|
|
192
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Rotates the wide (DOWN two layers) clockwise or counterclockwise.
|
|
204
|
+
*/
|
|
205
|
+
rotateDw(clockwise = true) {
|
|
206
|
+
if (clockwise) {
|
|
207
|
+
this.#rotateDw(true);
|
|
208
|
+
this.MOVES.push("Dw");
|
|
209
|
+
} else {
|
|
210
|
+
this.#rotateDw(false);
|
|
211
|
+
this.MOVES.push("Dw'");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
#rotateDw(clockwise = true) {
|
|
216
|
+
if (clockwise) {
|
|
217
|
+
this.#rotateY(false);
|
|
218
|
+
this.#rotateU(true);
|
|
219
|
+
} else {
|
|
220
|
+
this.#rotateY(true);
|
|
221
|
+
this.#rotateU(false);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Rotates the wide (UPPER two layers) clockwise or counterclockwise.
|
|
227
|
+
*/
|
|
228
|
+
rotateUw(clockwise = true) {
|
|
229
|
+
if (clockwise) {
|
|
230
|
+
this.#rotateUw(true);
|
|
231
|
+
this.MOVES.push("Uw");
|
|
232
|
+
} else {
|
|
233
|
+
this.#rotateUw(false);
|
|
234
|
+
this.MOVES.push("Uw'");
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
#rotateUw(clockwise = true) {
|
|
239
|
+
if (clockwise) {
|
|
240
|
+
this.#rotateY(true);
|
|
241
|
+
this.#rotateD(true);
|
|
242
|
+
} else {
|
|
243
|
+
this.#rotateY(false);
|
|
244
|
+
this.#rotateD(false);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Rotates the wide (RIGHT two layers) clockwise or counterclockwise.
|
|
250
|
+
*/
|
|
251
|
+
rotateRw(clockwise = true) {
|
|
252
|
+
if (clockwise) {
|
|
253
|
+
this.#rotateRw(true);
|
|
254
|
+
this.MOVES.push("Rw");
|
|
255
|
+
} else {
|
|
256
|
+
this.#rotateRw(false);
|
|
257
|
+
this.MOVES.push("Rw'");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
#rotateRw(clockwise = true) {
|
|
262
|
+
if (clockwise) {
|
|
263
|
+
this.#rotateX(true);
|
|
264
|
+
this.#rotateL(true);
|
|
265
|
+
} else {
|
|
266
|
+
this.#rotateX(false);
|
|
267
|
+
this.#rotateL(false);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Rotates the wide (LEFT two layers) clockwise or counterclockwise.
|
|
273
|
+
*/
|
|
274
|
+
rotateLw(clockwise = true) {
|
|
275
|
+
if (clockwise) {
|
|
276
|
+
this.#rotateLw(true);
|
|
277
|
+
this.MOVES.push("Lw");
|
|
278
|
+
} else {
|
|
279
|
+
this.#rotateLw(false);
|
|
280
|
+
this.MOVES.push("Lw'");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
#rotateLw(clockwise = true) {
|
|
285
|
+
if (clockwise) {
|
|
286
|
+
// Lw equals x' R
|
|
287
|
+
this.#rotateX(false);
|
|
288
|
+
this.#rotateR(true);
|
|
289
|
+
} else {
|
|
290
|
+
this.#rotateX(true);
|
|
291
|
+
this.#rotateR(false);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Rotates the middle slice (M) parallel to L/R. Clockwise corresponds to Lw followed by L'.
|
|
297
|
+
*/
|
|
298
|
+
rotateM(clockwise = true) {
|
|
299
|
+
if (clockwise) {
|
|
300
|
+
this.#rotateM(true);
|
|
301
|
+
this.MOVES.push("M");
|
|
302
|
+
} else {
|
|
303
|
+
this.#rotateM(false);
|
|
304
|
+
this.MOVES.push("M'");
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
#rotateM(clockwise = true) {
|
|
309
|
+
if (clockwise) {
|
|
310
|
+
this.#rotateLw(true);
|
|
311
|
+
this.#rotateL(false);
|
|
312
|
+
} else {
|
|
313
|
+
this.#rotateLw(false);
|
|
314
|
+
this.#rotateL(true);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
193
318
|
/**
|
|
194
319
|
* Rotates the (x) axis clockwise or counterclockwise.
|
|
195
320
|
*/
|
|
@@ -235,6 +360,50 @@ class CubeEngine {
|
|
|
235
360
|
}
|
|
236
361
|
}
|
|
237
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Rotates the (z) axis clockwise or counterclockwise.
|
|
365
|
+
*/
|
|
366
|
+
rotateZ(clockwise = true) {
|
|
367
|
+
if (clockwise) {
|
|
368
|
+
this.#rotateZ(true);
|
|
369
|
+
this.MOVES.push("z");
|
|
370
|
+
} else {
|
|
371
|
+
this.#rotateZ(false);
|
|
372
|
+
this.MOVES.push("z'");
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
#rotateZ(clockwise = true) {
|
|
377
|
+
const tempUpper = structuredClone(this.STATES.UPPER);
|
|
378
|
+
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
379
|
+
const tempDown = structuredClone(this.STATES.DOWN);
|
|
380
|
+
const tempLeft = structuredClone(this.STATES.LEFT);
|
|
381
|
+
const tempFront = structuredClone(this.STATES.FRONT);
|
|
382
|
+
const tempBack = structuredClone(this.STATES.BACK);
|
|
383
|
+
|
|
384
|
+
if (clockwise) {
|
|
385
|
+
// Rotate faces on the rotation axis
|
|
386
|
+
this.STATES.FRONT = this.#switchMatrix(tempFront, true);
|
|
387
|
+
this.STATES.BACK = this.#switchMatrix(tempBack, false);
|
|
388
|
+
|
|
389
|
+
// Cycle U -> R -> D -> L -> U with proper orientation
|
|
390
|
+
this.STATES.RIGHT = this.#switchMatrix(tempUpper, true);
|
|
391
|
+
this.STATES.DOWN = this.#switchMatrix(tempRight, true);
|
|
392
|
+
this.STATES.LEFT = this.#switchMatrix(tempDown, true);
|
|
393
|
+
this.STATES.UPPER = this.#switchMatrix(tempLeft, true);
|
|
394
|
+
} else {
|
|
395
|
+
// Counterclockwise
|
|
396
|
+
this.STATES.FRONT = this.#switchMatrix(tempFront, false);
|
|
397
|
+
this.STATES.BACK = this.#switchMatrix(tempBack, true);
|
|
398
|
+
|
|
399
|
+
// Cycle U -> L -> D -> R -> U (inverse of clockwise), rotate CCW
|
|
400
|
+
this.STATES.RIGHT = this.#switchMatrix(tempDown, false);
|
|
401
|
+
this.STATES.DOWN = this.#switchMatrix(tempLeft, false);
|
|
402
|
+
this.STATES.LEFT = this.#switchMatrix(tempUpper, false);
|
|
403
|
+
this.STATES.UPPER = this.#switchMatrix(tempRight, false);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
238
407
|
/**
|
|
239
408
|
* Rotates the (y) axis clockwise or counterclockwise.
|
|
240
409
|
*/
|
|
@@ -343,6 +512,183 @@ class CubeEngine {
|
|
|
343
512
|
getMoves(asString = true) {
|
|
344
513
|
return asString ? this.MOVES.join(" ") : this.MOVES;
|
|
345
514
|
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Resets the cube to the solved state and clears the move history.
|
|
518
|
+
*/
|
|
519
|
+
reset() {
|
|
520
|
+
this.STATES = {
|
|
521
|
+
UPPER: [
|
|
522
|
+
[COLOR.W[0], COLOR.W[1], COLOR.W[2]],
|
|
523
|
+
[COLOR.W[3], COLOR.W[4], COLOR.W[5]],
|
|
524
|
+
[COLOR.W[6], COLOR.W[7], COLOR.W[8]],
|
|
525
|
+
],
|
|
526
|
+
LEFT: [
|
|
527
|
+
[COLOR.O[0], COLOR.O[1], COLOR.O[2]],
|
|
528
|
+
[COLOR.O[3], COLOR.O[4], COLOR.O[5]],
|
|
529
|
+
[COLOR.O[6], COLOR.O[7], COLOR.O[8]],
|
|
530
|
+
],
|
|
531
|
+
FRONT: [
|
|
532
|
+
[COLOR.G[0], COLOR.G[1], COLOR.G[2]],
|
|
533
|
+
[COLOR.G[3], COLOR.G[4], COLOR.G[5]],
|
|
534
|
+
[COLOR.G[6], COLOR.G[7], COLOR.G[8]],
|
|
535
|
+
],
|
|
536
|
+
RIGHT: [
|
|
537
|
+
[COLOR.R[0], COLOR.R[1], COLOR.R[2]],
|
|
538
|
+
[COLOR.R[3], COLOR.R[4], COLOR.R[5]],
|
|
539
|
+
[COLOR.R[6], COLOR.R[7], COLOR.R[8]],
|
|
540
|
+
],
|
|
541
|
+
BACK: [
|
|
542
|
+
[COLOR.B[0], COLOR.B[1], COLOR.B[2]],
|
|
543
|
+
[COLOR.B[3], COLOR.B[4], COLOR.B[5]],
|
|
544
|
+
[COLOR.B[6], COLOR.B[7], COLOR.B[8]],
|
|
545
|
+
],
|
|
546
|
+
DOWN: [
|
|
547
|
+
[COLOR.Y[0], COLOR.Y[1], COLOR.Y[2]],
|
|
548
|
+
[COLOR.Y[3], COLOR.Y[4], COLOR.Y[5]],
|
|
549
|
+
[COLOR.Y[6], COLOR.Y[7], COLOR.Y[8]],
|
|
550
|
+
],
|
|
551
|
+
};
|
|
552
|
+
this.MOVES = [];
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Applies a sequence of moves provided as a string.
|
|
557
|
+
* Supports: U, D, L, R, F, x, y, z; slice moves: M; and wide moves: Dw, Uw, Rw, Lw with optional ' for counterclockwise and 2 for double turns.
|
|
558
|
+
* @param {string} sequence - e.g. "R U' F R2 D Dw Uw Rw Rw' Lw Lw2 M M' M2"
|
|
559
|
+
* @param {object} options - { record: boolean } whether to record moves in history (default true)
|
|
560
|
+
*/
|
|
561
|
+
applyMoves(sequence, options = { record: false }) {
|
|
562
|
+
const record = options?.record !== false;
|
|
563
|
+
this.#applyMovesFromString(sequence, record);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Internal: parses and applies moves. If record=false, uses private methods to avoid logging.
|
|
567
|
+
#applyMovesFromString(sequence, record = true) {
|
|
568
|
+
if (typeof sequence !== "string") return;
|
|
569
|
+
const tokens = sequence
|
|
570
|
+
.split(/\s+/)
|
|
571
|
+
.map((t) => t.trim())
|
|
572
|
+
.filter((t) => t.length > 0);
|
|
573
|
+
|
|
574
|
+
for (const token of tokens) {
|
|
575
|
+
const base = token[0];
|
|
576
|
+
const rest = token.slice(1);
|
|
577
|
+
const isDouble = rest.includes("2");
|
|
578
|
+
const isPrime = rest.includes("'");
|
|
579
|
+
|
|
580
|
+
const exec = (fnClockwise, fnCounter) => {
|
|
581
|
+
if (isDouble) {
|
|
582
|
+
// Double turns ignore prime; do two clockwise quarter-turns
|
|
583
|
+
fnClockwise();
|
|
584
|
+
fnClockwise();
|
|
585
|
+
} else {
|
|
586
|
+
if (isPrime) {
|
|
587
|
+
fnCounter();
|
|
588
|
+
} else {
|
|
589
|
+
fnClockwise();
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
switch (base) {
|
|
595
|
+
case 'U':
|
|
596
|
+
{
|
|
597
|
+
const isWide = /w/i.test(rest);
|
|
598
|
+
if (isWide) {
|
|
599
|
+
exec(
|
|
600
|
+
() => (record ? this.rotateUw(true) : this.#rotateUw(true)),
|
|
601
|
+
() => (record ? this.rotateUw(false) : this.#rotateUw(false))
|
|
602
|
+
);
|
|
603
|
+
} else {
|
|
604
|
+
exec(
|
|
605
|
+
() => (record ? this.rotateU(true) : this.#rotateU(true)),
|
|
606
|
+
() => (record ? this.rotateU(false) : this.#rotateU(false))
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
break;
|
|
611
|
+
case 'D':
|
|
612
|
+
{
|
|
613
|
+
const isWide = /w/i.test(rest);
|
|
614
|
+
if (isWide) {
|
|
615
|
+
exec(
|
|
616
|
+
() => (record ? this.rotateDw(true) : this.#rotateDw(true)),
|
|
617
|
+
() => (record ? this.rotateDw(false) : this.#rotateDw(false))
|
|
618
|
+
);
|
|
619
|
+
} else {
|
|
620
|
+
exec(
|
|
621
|
+
() => (record ? this.rotateD(true) : this.#rotateD(true)),
|
|
622
|
+
() => (record ? this.rotateD(false) : this.#rotateD(false))
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
break;
|
|
627
|
+
case 'L':
|
|
628
|
+
{
|
|
629
|
+
const isWide = /w/i.test(rest);
|
|
630
|
+
if (isWide) {
|
|
631
|
+
exec(
|
|
632
|
+
() => (record ? this.rotateLw(true) : this.#rotateLw(true)),
|
|
633
|
+
() => (record ? this.rotateLw(false) : this.#rotateLw(false))
|
|
634
|
+
);
|
|
635
|
+
} else {
|
|
636
|
+
exec(
|
|
637
|
+
() => (record ? this.rotateL(true) : this.#rotateL(true)),
|
|
638
|
+
() => (record ? this.rotateL(false) : this.#rotateL(false))
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
break;
|
|
643
|
+
case 'R':
|
|
644
|
+
{
|
|
645
|
+
const isWide = /w/i.test(rest);
|
|
646
|
+
if (isWide) {
|
|
647
|
+
exec(
|
|
648
|
+
() => (record ? this.rotateRw(true) : this.#rotateRw(true)),
|
|
649
|
+
() => (record ? this.rotateRw(false) : this.#rotateRw(false))
|
|
650
|
+
);
|
|
651
|
+
} else {
|
|
652
|
+
exec(
|
|
653
|
+
() => (record ? this.rotateR(true) : this.#rotateR(true)),
|
|
654
|
+
() => (record ? this.rotateR(false) : this.#rotateR(false))
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
break;
|
|
659
|
+
case 'F':
|
|
660
|
+
exec(
|
|
661
|
+
() => (record ? this.rotateF(true) : this.#rotateF(true)),
|
|
662
|
+
() => (record ? this.rotateF(false) : this.#rotateF(false))
|
|
663
|
+
);
|
|
664
|
+
break;
|
|
665
|
+
case 'x':
|
|
666
|
+
exec(
|
|
667
|
+
() => (record ? this.rotateX(true) : this.#rotateX(true)),
|
|
668
|
+
() => (record ? this.rotateX(false) : this.#rotateX(false))
|
|
669
|
+
);
|
|
670
|
+
break;
|
|
671
|
+
case 'y':
|
|
672
|
+
exec(
|
|
673
|
+
() => (record ? this.rotateY(true) : this.#rotateY(true)),
|
|
674
|
+
() => (record ? this.rotateY(false) : this.#rotateY(false))
|
|
675
|
+
);
|
|
676
|
+
break;
|
|
677
|
+
case 'z':
|
|
678
|
+
exec(
|
|
679
|
+
() => (record ? this.rotateZ(true) : this.#rotateZ(true)),
|
|
680
|
+
() => (record ? this.rotateZ(false) : this.#rotateZ(false))
|
|
681
|
+
);
|
|
682
|
+
break;
|
|
683
|
+
case 'M':
|
|
684
|
+
exec(
|
|
685
|
+
() => (record ? this.rotateM(true) : this.#rotateM(true)),
|
|
686
|
+
() => (record ? this.rotateM(false) : this.#rotateM(false))
|
|
687
|
+
);
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
346
692
|
}
|
|
347
693
|
|
|
348
694
|
const COLOR = {
|