@rednaxela101/cubing 0.63.5

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 (136) hide show
  1. package/README.md +120 -0
  2. package/alg/index.d.ts +1 -0
  3. package/bluetooth/index.d.ts +1 -0
  4. package/dist/bin/chunks/chunk-22VWCGBC.js +13 -0
  5. package/dist/bin/chunks/chunk-22VWCGBC.js.map +7 -0
  6. package/dist/bin/order.js +59 -0
  7. package/dist/bin/order.js.map +7 -0
  8. package/dist/bin/puzzle-geometry-bin.js +407 -0
  9. package/dist/bin/puzzle-geometry-bin.js.map +7 -0
  10. package/dist/bin/scramble.js +188 -0
  11. package/dist/bin/scramble.js.map +7 -0
  12. package/dist/bin/svg.js +56 -0
  13. package/dist/bin/svg.js.map +7 -0
  14. package/dist/lib/cubing/alg/index.d.ts +2 -0
  15. package/dist/lib/cubing/alg/index.js +43 -0
  16. package/dist/lib/cubing/alg/index.js.map +7 -0
  17. package/dist/lib/cubing/bluetooth/index.d.ts +189 -0
  18. package/dist/lib/cubing/bluetooth/index.js +2271 -0
  19. package/dist/lib/cubing/bluetooth/index.js.map +7 -0
  20. package/dist/lib/cubing/chunks/big-puzzle-orientation-BA6QHO5C.js +68 -0
  21. package/dist/lib/cubing/chunks/big-puzzle-orientation-BA6QHO5C.js.map +7 -0
  22. package/dist/lib/cubing/chunks/chunk-2VJB4TMH.js +1774 -0
  23. package/dist/lib/cubing/chunks/chunk-2VJB4TMH.js.map +7 -0
  24. package/dist/lib/cubing/chunks/chunk-52ZXJEUO.js +665 -0
  25. package/dist/lib/cubing/chunks/chunk-52ZXJEUO.js.map +7 -0
  26. package/dist/lib/cubing/chunks/chunk-56VZAEPF.js +274 -0
  27. package/dist/lib/cubing/chunks/chunk-56VZAEPF.js.map +7 -0
  28. package/dist/lib/cubing/chunks/chunk-7GUL3OBQ.js +9 -0
  29. package/dist/lib/cubing/chunks/chunk-7GUL3OBQ.js.map +7 -0
  30. package/dist/lib/cubing/chunks/chunk-7L7BJSIM.js +21 -0
  31. package/dist/lib/cubing/chunks/chunk-7L7BJSIM.js.map +7 -0
  32. package/dist/lib/cubing/chunks/chunk-AESPJKN6.js +265 -0
  33. package/dist/lib/cubing/chunks/chunk-AESPJKN6.js.map +7 -0
  34. package/dist/lib/cubing/chunks/chunk-C2Q347XS.js +89 -0
  35. package/dist/lib/cubing/chunks/chunk-C2Q347XS.js.map +7 -0
  36. package/dist/lib/cubing/chunks/chunk-CGBMJBU3.js +1195 -0
  37. package/dist/lib/cubing/chunks/chunk-CGBMJBU3.js.map +7 -0
  38. package/dist/lib/cubing/chunks/chunk-HZQONEMD.js +249 -0
  39. package/dist/lib/cubing/chunks/chunk-HZQONEMD.js.map +7 -0
  40. package/dist/lib/cubing/chunks/chunk-IAGCVPL3.js +1069 -0
  41. package/dist/lib/cubing/chunks/chunk-IAGCVPL3.js.map +7 -0
  42. package/dist/lib/cubing/chunks/chunk-NAPITA3L.js +1 -0
  43. package/dist/lib/cubing/chunks/chunk-NAPITA3L.js.map +7 -0
  44. package/dist/lib/cubing/chunks/chunk-XPDJUSZ7.js +1876 -0
  45. package/dist/lib/cubing/chunks/chunk-XPDJUSZ7.js.map +7 -0
  46. package/dist/lib/cubing/chunks/chunk-YSI6PF35.js +619 -0
  47. package/dist/lib/cubing/chunks/chunk-YSI6PF35.js.map +7 -0
  48. package/dist/lib/cubing/chunks/inside-LG2EAKCL.js +557 -0
  49. package/dist/lib/cubing/chunks/inside-LG2EAKCL.js.map +7 -0
  50. package/dist/lib/cubing/chunks/puzzles-dynamic-2x2x2-JYJJXB4V.js +142 -0
  51. package/dist/lib/cubing/chunks/puzzles-dynamic-2x2x2-JYJJXB4V.js.map +7 -0
  52. package/dist/lib/cubing/chunks/puzzles-dynamic-3x3x3-FYXD7SIU.js +365 -0
  53. package/dist/lib/cubing/chunks/puzzles-dynamic-3x3x3-FYXD7SIU.js.map +7 -0
  54. package/dist/lib/cubing/chunks/puzzles-dynamic-4x4x4-AIGABOAR.js +132 -0
  55. package/dist/lib/cubing/chunks/puzzles-dynamic-4x4x4-AIGABOAR.js.map +7 -0
  56. package/dist/lib/cubing/chunks/puzzles-dynamic-5x5x5-JUNRX27W.js +277 -0
  57. package/dist/lib/cubing/chunks/puzzles-dynamic-5x5x5-JUNRX27W.js.map +7 -0
  58. package/dist/lib/cubing/chunks/puzzles-dynamic-clock-USGQTDPO.js +836 -0
  59. package/dist/lib/cubing/chunks/puzzles-dynamic-clock-USGQTDPO.js.map +7 -0
  60. package/dist/lib/cubing/chunks/puzzles-dynamic-fto-WJHMLYCJ.js +100 -0
  61. package/dist/lib/cubing/chunks/puzzles-dynamic-fto-WJHMLYCJ.js.map +7 -0
  62. package/dist/lib/cubing/chunks/puzzles-dynamic-megaminx-2LVHIDL4.js +224 -0
  63. package/dist/lib/cubing/chunks/puzzles-dynamic-megaminx-2LVHIDL4.js.map +7 -0
  64. package/dist/lib/cubing/chunks/puzzles-dynamic-pyraminx-7UWX4HHI.js +93 -0
  65. package/dist/lib/cubing/chunks/puzzles-dynamic-pyraminx-7UWX4HHI.js.map +7 -0
  66. package/dist/lib/cubing/chunks/puzzles-dynamic-square1-PQEKBPFN.js +842 -0
  67. package/dist/lib/cubing/chunks/puzzles-dynamic-square1-PQEKBPFN.js.map +7 -0
  68. package/dist/lib/cubing/chunks/search-dynamic-sgs-2x2x2-XFKQ4VJS.js +125 -0
  69. package/dist/lib/cubing/chunks/search-dynamic-sgs-2x2x2-XFKQ4VJS.js.map +7 -0
  70. package/dist/lib/cubing/chunks/search-dynamic-sgs-megaminx-ZDOOLEDW.js +1564 -0
  71. package/dist/lib/cubing/chunks/search-dynamic-sgs-megaminx-ZDOOLEDW.js.map +7 -0
  72. package/dist/lib/cubing/chunks/search-dynamic-sgs-pyraminx-W6UJWBYY.js +108 -0
  73. package/dist/lib/cubing/chunks/search-dynamic-sgs-pyraminx-W6UJWBYY.js.map +7 -0
  74. package/dist/lib/cubing/chunks/search-dynamic-sgs-skewb-FXGKV4KD.js +125 -0
  75. package/dist/lib/cubing/chunks/search-dynamic-sgs-skewb-FXGKV4KD.js.map +7 -0
  76. package/dist/lib/cubing/chunks/search-dynamic-sgs-unofficial-YK6HA7BK.js +644 -0
  77. package/dist/lib/cubing/chunks/search-dynamic-sgs-unofficial-YK6HA7BK.js.map +7 -0
  78. package/dist/lib/cubing/chunks/search-dynamic-solve-3x3x3-DLMAGPXS.js +2549 -0
  79. package/dist/lib/cubing/chunks/search-dynamic-solve-3x3x3-DLMAGPXS.js.map +7 -0
  80. package/dist/lib/cubing/chunks/search-dynamic-solve-4x4x4-NONXQHOJ.js +2923 -0
  81. package/dist/lib/cubing/chunks/search-dynamic-solve-4x4x4-NONXQHOJ.js.map +7 -0
  82. package/dist/lib/cubing/chunks/search-dynamic-solve-fto-3GQ2HLSW.js +1405 -0
  83. package/dist/lib/cubing/chunks/search-dynamic-solve-fto-3GQ2HLSW.js.map +7 -0
  84. package/dist/lib/cubing/chunks/search-worker-entry.js +19 -0
  85. package/dist/lib/cubing/chunks/search-worker-entry.js.map +7 -0
  86. package/dist/lib/cubing/chunks/square1-stickerings-W2ZLZWIN.js +73 -0
  87. package/dist/lib/cubing/chunks/square1-stickerings-W2ZLZWIN.js.map +7 -0
  88. package/dist/lib/cubing/chunks/twips-2RNTWYNZ.js +433 -0
  89. package/dist/lib/cubing/chunks/twips-2RNTWYNZ.js.map +7 -0
  90. package/dist/lib/cubing/chunks/twips_wasm_bg-TJNYGA2C-23XTPLIK.js +10 -0
  91. package/dist/lib/cubing/chunks/twips_wasm_bg-TJNYGA2C-23XTPLIK.js.map +7 -0
  92. package/dist/lib/cubing/chunks/twisty-dynamic-3d-JO6OGKOF.js +2424 -0
  93. package/dist/lib/cubing/chunks/twisty-dynamic-3d-JO6OGKOF.js.map +7 -0
  94. package/dist/lib/cubing/index-BX6f56uo.d.ts +76 -0
  95. package/dist/lib/cubing/index-CcRu94bx.d.ts +2622 -0
  96. package/dist/lib/cubing/kpuzzle/index.d.ts +2 -0
  97. package/dist/lib/cubing/kpuzzle/index.js +12 -0
  98. package/dist/lib/cubing/kpuzzle/index.js.map +7 -0
  99. package/dist/lib/cubing/notation/index.d.ts +32 -0
  100. package/dist/lib/cubing/notation/index.js +20 -0
  101. package/dist/lib/cubing/notation/index.js.map +7 -0
  102. package/dist/lib/cubing/outside-BCzgSYQ_.d.ts +38 -0
  103. package/dist/lib/cubing/protocol/index.d.ts +28 -0
  104. package/dist/lib/cubing/protocol/index.js +20 -0
  105. package/dist/lib/cubing/protocol/index.js.map +7 -0
  106. package/dist/lib/cubing/puzzle-geometry/index.d.ts +2 -0
  107. package/dist/lib/cubing/puzzle-geometry/index.js +5024 -0
  108. package/dist/lib/cubing/puzzle-geometry/index.js.map +7 -0
  109. package/dist/lib/cubing/puzzles/index.d.ts +2 -0
  110. package/dist/lib/cubing/puzzles/index.js +23 -0
  111. package/dist/lib/cubing/puzzles/index.js.map +7 -0
  112. package/dist/lib/cubing/scramble/index.d.ts +2 -0
  113. package/dist/lib/cubing/scramble/index.js +16 -0
  114. package/dist/lib/cubing/scramble/index.js.map +7 -0
  115. package/dist/lib/cubing/search/index.d.ts +7 -0
  116. package/dist/lib/cubing/search/index.js +37 -0
  117. package/dist/lib/cubing/search/index.js.map +7 -0
  118. package/dist/lib/cubing/stream/index.d.ts +2 -0
  119. package/dist/lib/cubing/stream/index.js +111 -0
  120. package/dist/lib/cubing/stream/index.js.map +7 -0
  121. package/dist/lib/cubing/twisty/index.d.ts +2 -0
  122. package/dist/lib/cubing/twisty/index.js +6236 -0
  123. package/dist/lib/cubing/twisty/index.js.map +7 -0
  124. package/experimental-json-schema/kpuzzle/KPatternData.schema.json +34 -0
  125. package/experimental-json-schema/kpuzzle/KPuzzleDefinition.schema.json +97 -0
  126. package/experimental-json-schema/kpuzzle/KTransformationData.schema.json +27 -0
  127. package/kpuzzle/index.d.ts +1 -0
  128. package/notation/index.d.ts +1 -0
  129. package/package.json +146 -0
  130. package/protocol/index.d.ts +1 -0
  131. package/puzzle-geometry/index.d.ts +1 -0
  132. package/puzzles/index.d.ts +1 -0
  133. package/scramble/index.d.ts +1 -0
  134. package/search/index.d.ts +1 -0
  135. package/stream/index.d.ts +1 -0
  136. package/twisty/index.d.ts +1 -0
@@ -0,0 +1,2424 @@
1
+ import {
2
+ TAU,
3
+ bulk3DCode,
4
+ haveStartedSharingRenderers,
5
+ hintFaceletStyles
6
+ } from "./chunk-CGBMJBU3.js";
7
+ import "./chunk-YSI6PF35.js";
8
+ import {
9
+ cube3x3x3,
10
+ getFaceletStickeringMask
11
+ } from "./chunk-2VJB4TMH.js";
12
+ import "./chunk-52ZXJEUO.js";
13
+ import {
14
+ Move
15
+ } from "./chunk-XPDJUSZ7.js";
16
+
17
+ // src/cubing/twisty/views/3D/puzzles/Cube3D.ts
18
+ import { BackSide, DoubleSide, FrontSide } from "three/src/constants.js";
19
+ import { BufferAttribute } from "three/src/core/BufferAttribute.js";
20
+ import { BufferGeometry } from "three/src/core/BufferGeometry.js";
21
+ import { Object3D } from "three/src/core/Object3D.js";
22
+ import { BoxGeometry } from "three/src/geometries/BoxGeometry.js";
23
+ import { TextureLoader } from "three/src/loaders/TextureLoader.js";
24
+ import { MeshBasicMaterial } from "three/src/materials/MeshBasicMaterial.js";
25
+ import { Color } from "three/src/math/Color.js";
26
+ import { Euler } from "three/src/math/Euler.js";
27
+ import { Matrix4 } from "three/src/math/Matrix4.js";
28
+ import { Quaternion } from "three/src/math/Quaternion.js";
29
+ import { Vector2 } from "three/src/math/Vector2.js";
30
+ import { Vector3 } from "three/src/math/Vector3.js";
31
+ import { Group } from "three/src/objects/Group.js";
32
+ import { Mesh } from "three/src/objects/Mesh.js";
33
+
34
+ // src/cubing/twisty/controllers/easing.ts
35
+ function smootherStep(x) {
36
+ return x * x * x * (10 - x * (15 - 6 * x));
37
+ }
38
+
39
+ // src/cubing/twisty/views/3D/puzzles/Cube3D.ts
40
+ var svgLoader = new TextureLoader();
41
+ var ignoredMaterial = new MeshBasicMaterial({
42
+ color: new Color(6710886).convertLinearToSRGB()
43
+ });
44
+ var ignoredMaterialHint = new MeshBasicMaterial({
45
+ color: new Color(13421772).convertLinearToSRGB(),
46
+ side: BackSide,
47
+ transparent: true,
48
+ opacity: 0.75
49
+ });
50
+ var invisibleMaterial = new MeshBasicMaterial({
51
+ visible: false
52
+ });
53
+ var orientedMaterial = new MeshBasicMaterial({
54
+ color: 4513228
55
+ });
56
+ var orientedMaterialHint = new MeshBasicMaterial({
57
+ color: 4513228,
58
+ side: BackSide,
59
+ transparent: true,
60
+ opacity: 0.5
61
+ });
62
+ var experimentalOriented2Material = new MeshBasicMaterial({
63
+ color: 16776618
64
+ });
65
+ var experimentalOriented2MaterialHint = new MeshBasicMaterial({
66
+ color: 16775545,
67
+ side: BackSide,
68
+ transparent: true,
69
+ opacity: 0.5
70
+ });
71
+ var mysteryMaterial = new MeshBasicMaterial({
72
+ color: 15911883
73
+ });
74
+ var mysterMaterialHint = new MeshBasicMaterial({
75
+ color: 15911883,
76
+ side: BackSide,
77
+ transparent: true,
78
+ opacity: 0.5
79
+ });
80
+ var AxisInfo = class {
81
+ constructor(vector, fromZ, color, dimColor, hintOpacityScale, options) {
82
+ this.vector = vector;
83
+ this.fromZ = fromZ;
84
+ this.color = color;
85
+ this.dimColor = dimColor;
86
+ this.hintOpacityScale = hintOpacityScale;
87
+ const colorLinearSRGB = new Color(color).convertLinearToSRGB();
88
+ const dimColorLinearSRGB = new Color(dimColor).convertLinearToSRGB();
89
+ this.stickerMaterial = {
90
+ regular: new MeshBasicMaterial({
91
+ color: colorLinearSRGB,
92
+ side: FrontSide
93
+ // TODO: set to `DoubleSide` when hint facelets are disabled.
94
+ }),
95
+ dim: new MeshBasicMaterial({
96
+ color: dimColorLinearSRGB,
97
+ side: FrontSide
98
+ // TODO: set to `DoubleSide` when hint facelets are disabled.
99
+ }),
100
+ oriented: orientedMaterial,
101
+ experimentalOriented2: experimentalOriented2Material,
102
+ ignored: ignoredMaterial,
103
+ invisible: invisibleMaterial,
104
+ mystery: mysteryMaterial
105
+ };
106
+ this.hintStickerMaterial = {
107
+ regular: new MeshBasicMaterial({
108
+ color: new Color(options?.hintColor ?? color).convertLinearToSRGB(),
109
+ side: BackSide,
110
+ transparent: true,
111
+ opacity: 0.5 * hintOpacityScale
112
+ }),
113
+ dim: new MeshBasicMaterial({
114
+ color: new Color(
115
+ options?.hintDimColor ?? dimColor
116
+ ).convertLinearToSRGB(),
117
+ side: BackSide,
118
+ transparent: true,
119
+ opacity: 0.5 * hintOpacityScale
120
+ }),
121
+ oriented: orientedMaterialHint,
122
+ experimentalOriented2: experimentalOriented2MaterialHint,
123
+ ignored: ignoredMaterialHint,
124
+ invisible: invisibleMaterial,
125
+ mystery: mysterMaterialHint
126
+ };
127
+ }
128
+ vector;
129
+ fromZ;
130
+ color;
131
+ dimColor;
132
+ hintOpacityScale;
133
+ stickerMaterial;
134
+ hintStickerMaterial;
135
+ };
136
+ var axesInfo = [
137
+ new AxisInfo(
138
+ new Vector3(0, 1, 0),
139
+ new Euler(-TAU / 4, 0, 0),
140
+ 16777215,
141
+ 14540253,
142
+ 1.25
143
+ ),
144
+ new AxisInfo(
145
+ new Vector3(-1, 0, 0),
146
+ new Euler(0, -TAU / 4, 0),
147
+ 16750848,
148
+ 8934656,
149
+ 1,
150
+ { hintDimColor: 8930304 }
151
+ ),
152
+ new AxisInfo(
153
+ new Vector3(0, 0, 1),
154
+ new Euler(0, 0, 0),
155
+ 65280,
156
+ 34816,
157
+ 1,
158
+ { hintDimColor: 39168 }
159
+ ),
160
+ new AxisInfo(
161
+ new Vector3(1, 0, 0),
162
+ new Euler(0, TAU / 4, 0),
163
+ 16711680,
164
+ 6684672,
165
+ 1,
166
+ { hintDimColor: 6684672 }
167
+ ),
168
+ new AxisInfo(
169
+ new Vector3(0, 0, -1),
170
+ new Euler(0, TAU / 2, 0),
171
+ 2254591,
172
+ 1127304,
173
+ 0.75,
174
+ { hintDimColor: 6246 }
175
+ ),
176
+ new AxisInfo(
177
+ new Vector3(0, -1, 0),
178
+ new Euler(TAU / 4, 0, 0),
179
+ 16776960,
180
+ 8947712,
181
+ 1.25,
182
+ { hintDimColor: 14540032 }
183
+ )
184
+ ];
185
+ var face = {
186
+ U: 0,
187
+ L: 1,
188
+ F: 2,
189
+ R: 3,
190
+ B: 4,
191
+ D: 5
192
+ };
193
+ var familyToAxis = {
194
+ U: face["U"],
195
+ u: face["U"],
196
+ Uw: face["U"],
197
+ Uv: face["U"],
198
+ y: face["U"],
199
+ L: face["L"],
200
+ l: face["L"],
201
+ Lw: face["L"],
202
+ Lv: face["L"],
203
+ M: face["L"],
204
+ F: face["F"],
205
+ f: face["F"],
206
+ Fw: face["F"],
207
+ Fv: face["F"],
208
+ S: face["F"],
209
+ z: face["F"],
210
+ R: face["R"],
211
+ r: face["R"],
212
+ Rw: face["R"],
213
+ Rv: face["R"],
214
+ x: face["R"],
215
+ B: face["B"],
216
+ b: face["B"],
217
+ Bw: face["B"],
218
+ Bv: face["B"],
219
+ D: face["D"],
220
+ d: face["D"],
221
+ Dw: face["D"],
222
+ Dv: face["D"],
223
+ E: face["D"]
224
+ };
225
+ var cubieDimensions = {
226
+ // stickerWidth: 0.85, // Now `faceletScale` in options.
227
+ stickerElevation: 0.503,
228
+ foundationWidth: 1,
229
+ defaultHintStickerElevation: 1.45
230
+ };
231
+ var EXPERIMENTAL_PICTURE_CUBE_HINT_ELEVATION = 2;
232
+ var cube3DOptionsDefaults = {
233
+ showMainStickers: true,
234
+ hintFacelets: "floating",
235
+ showFoundation: true,
236
+ experimentalStickeringMask: void 0,
237
+ foundationSprite: null,
238
+ hintSprite: null,
239
+ initialHintFaceletsAnimation: "auto",
240
+ faceletScale: "auto",
241
+ hintFaceletsElevation: "auto"
242
+ };
243
+ var DEFAULT_STICKER_SCALE = 0.85;
244
+ function getFaceletScale(options) {
245
+ if (typeof options.faceletScale === "undefined" || options.faceletScale === "auto") {
246
+ return DEFAULT_STICKER_SCALE;
247
+ }
248
+ return options.faceletScale;
249
+ }
250
+ var blackMesh = new MeshBasicMaterial({
251
+ color: 0,
252
+ opacity: 1,
253
+ transparent: true
254
+ });
255
+ var blackTranslucentMesh = new MeshBasicMaterial({
256
+ color: 0,
257
+ opacity: 0.3,
258
+ transparent: true
259
+ });
260
+ var CubieDef = class {
261
+ // stickerFaceNames can be e.g. ["U", "F", "R"], "UFR" if every face is a single letter.
262
+ constructor(orbit, stickerFaceNames, q) {
263
+ this.orbit = orbit;
264
+ const individualStickerFaceNames = typeof stickerFaceNames === "string" ? stickerFaceNames.split("") : stickerFaceNames;
265
+ this.stickerFaces = individualStickerFaceNames.map((s) => face[s]);
266
+ this.matrix = new Matrix4();
267
+ this.matrix.setPosition(firstPiecePosition[orbit]);
268
+ this.matrix.premultiply(new Matrix4().makeRotationFromQuaternion(q));
269
+ }
270
+ orbit;
271
+ matrix;
272
+ stickerFaces;
273
+ };
274
+ function t(v, t4) {
275
+ return new Quaternion().setFromAxisAngle(v, TAU * t4 / 4);
276
+ }
277
+ var r = {
278
+ O: new Vector3(0, 0, 0),
279
+ U: new Vector3(0, -1, 0),
280
+ L: new Vector3(1, 0, 0),
281
+ F: new Vector3(0, 0, -1),
282
+ R: new Vector3(-1, 0, 0),
283
+ B: new Vector3(0, 0, 1),
284
+ D: new Vector3(0, 1, 0)
285
+ };
286
+ var firstPiecePosition = {
287
+ EDGES: new Vector3(0, 1, 1),
288
+ CORNERS: new Vector3(1, 1, 1),
289
+ CENTERS: new Vector3(0, 1, 0)
290
+ };
291
+ var orientationRotation = {
292
+ EDGES: [0, 1].map(
293
+ (i) => new Matrix4().makeRotationAxis(
294
+ firstPiecePosition["EDGES"].clone().normalize(),
295
+ -i * TAU / 2
296
+ )
297
+ ),
298
+ CORNERS: [0, 1, 2].map(
299
+ (i) => new Matrix4().makeRotationAxis(
300
+ firstPiecePosition["CORNERS"].clone().normalize(),
301
+ -i * TAU / 3
302
+ )
303
+ ),
304
+ CENTERS: [0, 1, 2, 3].map(
305
+ (i) => new Matrix4().makeRotationAxis(
306
+ firstPiecePosition["CENTERS"].clone().normalize(),
307
+ -i * TAU / 4
308
+ )
309
+ )
310
+ };
311
+ var cubieStickerOrder = [face["U"], face["F"], face["R"]];
312
+ var pieceDefs = {
313
+ EDGES: [
314
+ new CubieDef("EDGES", "UF", t(r.O, 0)),
315
+ new CubieDef("EDGES", "UR", t(r.U, 3)),
316
+ new CubieDef("EDGES", "UB", t(r.U, 2)),
317
+ new CubieDef("EDGES", "UL", t(r.U, 1)),
318
+ new CubieDef("EDGES", "DF", t(r.F, 2)),
319
+ new CubieDef("EDGES", "DR", t(r.F, 2).premultiply(t(r.D, 1))),
320
+ new CubieDef("EDGES", "DB", t(r.F, 2).premultiply(t(r.D, 2))),
321
+ new CubieDef("EDGES", "DL", t(r.F, 2).premultiply(t(r.D, 3))),
322
+ new CubieDef("EDGES", "FR", t(r.U, 3).premultiply(t(r.R, 3))),
323
+ new CubieDef("EDGES", "FL", t(r.U, 1).premultiply(t(r.R, 3))),
324
+ new CubieDef("EDGES", "BR", t(r.U, 3).premultiply(t(r.R, 1))),
325
+ new CubieDef("EDGES", "BL", t(r.U, 1).premultiply(t(r.R, 1)))
326
+ ],
327
+ CORNERS: [
328
+ new CubieDef("CORNERS", "UFR", t(r.O, 0)),
329
+ new CubieDef("CORNERS", "URB", t(r.U, 3)),
330
+ new CubieDef("CORNERS", "UBL", t(r.U, 2)),
331
+ new CubieDef("CORNERS", "ULF", t(r.U, 1)),
332
+ new CubieDef("CORNERS", "DRF", t(r.F, 2).premultiply(t(r.D, 1))),
333
+ new CubieDef("CORNERS", "DFL", t(r.F, 2).premultiply(t(r.D, 0))),
334
+ new CubieDef("CORNERS", "DLB", t(r.F, 2).premultiply(t(r.D, 3))),
335
+ new CubieDef("CORNERS", "DBR", t(r.F, 2).premultiply(t(r.D, 2)))
336
+ ],
337
+ CENTERS: [
338
+ new CubieDef("CENTERS", "U", t(r.O, 0)),
339
+ new CubieDef("CENTERS", "L", t(r.R, 3).premultiply(t(r.U, 1))),
340
+ new CubieDef("CENTERS", "F", t(r.R, 3)),
341
+ new CubieDef("CENTERS", "R", t(r.R, 3).premultiply(t(r.D, 1))),
342
+ new CubieDef("CENTERS", "B", t(r.R, 3).premultiply(t(r.D, 2))),
343
+ new CubieDef("CENTERS", "D", t(r.R, 2))
344
+ ]
345
+ };
346
+ var CUBE_SCALE = 1 / 3;
347
+ var pictureStickerCoords = {
348
+ EDGES: [
349
+ [
350
+ [0, 4, 6],
351
+ [0, 4, 5]
352
+ ],
353
+ [
354
+ [3, 5, 7],
355
+ [0, 7, 5]
356
+ ],
357
+ [
358
+ [2, 4, 8],
359
+ [0, 10, 5]
360
+ ],
361
+ [
362
+ [1, 3, 7],
363
+ [0, 1, 5]
364
+ ],
365
+ [
366
+ [2, 4, 2],
367
+ [2, 4, 3]
368
+ ],
369
+ [
370
+ [3, 5, 1],
371
+ [2, 7, 3]
372
+ ],
373
+ [
374
+ [0, 4, 0],
375
+ [2, 10, 3]
376
+ ],
377
+ [
378
+ [1, 3, 1],
379
+ [2, 1, 3]
380
+ ],
381
+ [
382
+ [3, 5, 4],
383
+ [3, 6, 4]
384
+ ],
385
+ [
386
+ [1, 3, 4],
387
+ [1, 2, 4]
388
+ ],
389
+ [
390
+ [1, 9, 4],
391
+ [1, 8, 4]
392
+ ],
393
+ [
394
+ [3, 11, 4],
395
+ [3, 0, 4]
396
+ ]
397
+ ],
398
+ CORNERS: [
399
+ [
400
+ [0, 5, 6],
401
+ [0, 5, 5],
402
+ [0, 6, 5]
403
+ ],
404
+ [
405
+ [3, 5, 8],
406
+ [0, 8, 5],
407
+ [0, 9, 5]
408
+ ],
409
+ [
410
+ [2, 3, 8],
411
+ [0, 11, 5],
412
+ [0, 0, 5]
413
+ ],
414
+ [
415
+ [1, 3, 6],
416
+ [0, 2, 5],
417
+ [0, 3, 5]
418
+ ],
419
+ [
420
+ [3, 5, 2],
421
+ [2, 6, 3],
422
+ [2, 5, 3]
423
+ ],
424
+ [
425
+ [2, 3, 2],
426
+ [2, 3, 3],
427
+ [2, 2, 3]
428
+ ],
429
+ [
430
+ [1, 3, 0],
431
+ [2, 0, 3],
432
+ [2, 11, 3]
433
+ ],
434
+ [
435
+ [0, 5, 0],
436
+ [2, 9, 3],
437
+ [2, 8, 3]
438
+ ]
439
+ ],
440
+ CENTERS: [
441
+ [[0, 4, 7]],
442
+ [[0, 1, 4]],
443
+ [[0, 4, 4]],
444
+ [[0, 7, 4]],
445
+ [[0, 10, 4]],
446
+ [[0, 4, 1]]
447
+ ]
448
+ };
449
+ var sharedCubieFoundationGeometryCache = null;
450
+ function sharedCubieFoundationGeometry() {
451
+ return sharedCubieFoundationGeometryCache ?? (sharedCubieFoundationGeometryCache = new BoxGeometry(
452
+ cubieDimensions.foundationWidth,
453
+ cubieDimensions.foundationWidth,
454
+ cubieDimensions.foundationWidth
455
+ ));
456
+ }
457
+ function newStickerGeometry() {
458
+ const r2 = new BufferGeometry();
459
+ const half = 0.5;
460
+ r2.setAttribute(
461
+ "position",
462
+ new BufferAttribute(
463
+ new Float32Array([
464
+ half,
465
+ half,
466
+ 0,
467
+ -half,
468
+ half,
469
+ 0,
470
+ half,
471
+ -half,
472
+ 0,
473
+ -half,
474
+ half,
475
+ 0,
476
+ -half,
477
+ -half,
478
+ 0,
479
+ half,
480
+ -half,
481
+ 0
482
+ ]),
483
+ 3
484
+ )
485
+ );
486
+ r2.setAttribute(
487
+ "uv",
488
+ new BufferAttribute(
489
+ new Float32Array([
490
+ 1,
491
+ 1,
492
+ 0,
493
+ 1,
494
+ 1,
495
+ 0,
496
+ 0,
497
+ 1,
498
+ 0,
499
+ 0,
500
+ 1,
501
+ 0,
502
+ 0,
503
+ 1,
504
+ 0,
505
+ 0,
506
+ 1,
507
+ 1,
508
+ 0,
509
+ 0,
510
+ 1,
511
+ 0,
512
+ 1,
513
+ 1
514
+ ]),
515
+ 2
516
+ )
517
+ );
518
+ return r2;
519
+ }
520
+ var sharedStickerGeometryCache;
521
+ function sharedStickerGeometry() {
522
+ return sharedStickerGeometryCache ??= newStickerGeometry();
523
+ }
524
+ var Cube3D = class extends Object3D {
525
+ constructor(kpuzzle, scheduleRenderCallback, options = {}) {
526
+ super();
527
+ this.kpuzzle = kpuzzle;
528
+ this.scheduleRenderCallback = scheduleRenderCallback;
529
+ this.options = { ...cube3DOptionsDefaults };
530
+ Object.assign(this.options, options);
531
+ if (this.kpuzzle.name() !== "3x3x3") {
532
+ throw new Error(
533
+ `Invalid puzzle for this Cube3D implementation: ${this.kpuzzle.name()}`
534
+ );
535
+ }
536
+ if (options.foundationSprite) {
537
+ this.setSprite(options.foundationSprite);
538
+ }
539
+ if (options.hintSprite) {
540
+ this.setHintSprite(options.hintSprite);
541
+ }
542
+ this.kpuzzleFaceletInfo = {};
543
+ for (const orbit in pieceDefs) {
544
+ const orbitFaceletInfo = [];
545
+ this.kpuzzleFaceletInfo[orbit] = orbitFaceletInfo;
546
+ this.pieces[orbit] = pieceDefs[orbit].map(
547
+ this.createCubie.bind(this, orbit, orbitFaceletInfo)
548
+ );
549
+ }
550
+ this.scale.set(CUBE_SCALE, CUBE_SCALE, CUBE_SCALE);
551
+ if (this.options.experimentalStickeringMask) {
552
+ this.setStickeringMask(this.options.experimentalStickeringMask);
553
+ }
554
+ void this.#animateRaiseHintFacelets();
555
+ if (this.options.faceletScale) {
556
+ this.experimentalSetFaceletScale(this.options.faceletScale);
557
+ }
558
+ if (typeof this.options["hintFaceletsElevation"] !== "undefined") {
559
+ this.#elevationRequest = this.options.hintFaceletsElevation;
560
+ }
561
+ }
562
+ kpuzzle;
563
+ scheduleRenderCallback;
564
+ kpuzzleFaceletInfo;
565
+ pieces = {};
566
+ options;
567
+ // TODO: Keep track of option-based meshes better.
568
+ experimentalHintStickerMeshes = [];
569
+ experimentalFoundationMeshes = [];
570
+ #setSpriteURL;
571
+ sprite = new Promise((resolve) => {
572
+ this.#setSpriteURL = (url) => {
573
+ svgLoader.load(url, resolve);
574
+ };
575
+ });
576
+ // TODO: Don't overwrite the static function.
577
+ // TODO: This doesn't work dynamically yet.
578
+ setSprite(texture) {
579
+ this.sprite = texture;
580
+ }
581
+ #setHintSpriteURL;
582
+ hintSprite = new Promise((resolve) => {
583
+ this.#setHintSpriteURL = (url) => {
584
+ svgLoader.load(url, resolve);
585
+ };
586
+ });
587
+ // TODO: Don't overwrite the static function.
588
+ // TODO: This doesn't work dynamically yet.
589
+ setHintSprite(texture) {
590
+ this.hintSprite = texture;
591
+ }
592
+ #sharedHintStickerGeometryCache;
593
+ #sharedHintStickerGeometry() {
594
+ return this.#sharedHintStickerGeometryCache ??= newStickerGeometry();
595
+ }
596
+ #elevationRequest;
597
+ setHintFaceletsElevation(elevation) {
598
+ if (elevation === this.#elevationRequest) {
599
+ return;
600
+ }
601
+ this.#cancelAnimateRaiseHintSticker = true;
602
+ this.#setHintFaceletsElevation(
603
+ typeof elevation === "number" ? elevation : cubieDimensions.defaultHintStickerElevation
604
+ );
605
+ this.#elevationRequest = elevation;
606
+ }
607
+ #lastHintStickerElevation = 0;
608
+ #setHintFaceletsElevation(elevation) {
609
+ this.#sharedHintStickerGeometry().translate(
610
+ 0,
611
+ 0,
612
+ elevation - this.#lastHintStickerElevation
613
+ );
614
+ this.#lastHintStickerElevation = elevation;
615
+ }
616
+ // TODO: support smooth physics
617
+ #cancelAnimateRaiseHintSticker = false;
618
+ // TODO: Generalize this into an animation mechanism.
619
+ async #animateRaiseHintFacelets() {
620
+ if (this.options.initialHintFaceletsAnimation === "none" || this.options.initialHintFaceletsAnimation !== "always" && haveStartedSharingRenderers()) {
621
+ return;
622
+ }
623
+ const targetElevation = typeof this.options.hintFaceletsElevation !== "undefined" && this.options.hintFaceletsElevation !== "auto" ? this.options.hintFaceletsElevation : cubieDimensions.defaultHintStickerElevation;
624
+ const translationRange = targetElevation - cubieDimensions.stickerElevation;
625
+ this.#setHintFaceletsElevation(cubieDimensions.stickerElevation);
626
+ await new Promise((resolve) => setTimeout(resolve, 500));
627
+ const hintStartTime = performance.now();
628
+ const translationDuration = 1e3;
629
+ function ease(x) {
630
+ return x * (2 - x);
631
+ }
632
+ const animateRaiseHintSticker = () => {
633
+ if (this.#cancelAnimateRaiseHintSticker) {
634
+ return;
635
+ }
636
+ const elapsed = performance.now() - hintStartTime;
637
+ const fraction = Math.min(elapsed / translationDuration, 1);
638
+ const newTranslation = ease(fraction) * translationRange + cubieDimensions.stickerElevation;
639
+ this.#setHintFaceletsElevation(newTranslation);
640
+ this.scheduleRenderCallback?.();
641
+ if (elapsed < translationDuration) {
642
+ requestAnimationFrame(animateRaiseHintSticker);
643
+ }
644
+ };
645
+ animateRaiseHintSticker();
646
+ }
647
+ // Can only be called once.
648
+ /** @deprecated */
649
+ experimentalSetStickerSpriteURL(stickerSpriteURL) {
650
+ this.#setSpriteURL?.(stickerSpriteURL);
651
+ }
652
+ // Can only be called once.
653
+ /** @deprecated */
654
+ experimentalSetHintStickerSpriteURL(hintStickerSpriteURL) {
655
+ this.#setHintSpriteURL?.(hintStickerSpriteURL);
656
+ }
657
+ setStickeringMask(stickeringMask) {
658
+ if (stickeringMask.specialBehaviour === "picture") {
659
+ for (const pieceInfos of Object.values(this.kpuzzleFaceletInfo)) {
660
+ for (const faceletInfos of pieceInfos) {
661
+ for (const faceletInfo of faceletInfos) {
662
+ faceletInfo.facelet.material = invisibleMaterial;
663
+ const { hintFacelet } = faceletInfo;
664
+ if (hintFacelet) {
665
+ hintFacelet.material = invisibleMaterial;
666
+ }
667
+ }
668
+ }
669
+ }
670
+ return;
671
+ }
672
+ this.options.experimentalStickeringMask = stickeringMask;
673
+ for (const [orbitName, orbitStickeringMask] of Object.entries(
674
+ stickeringMask.orbits
675
+ )) {
676
+ for (let pieceIdx = 0; pieceIdx < orbitStickeringMask.pieces.length; pieceIdx++) {
677
+ const pieceStickeringMask = orbitStickeringMask.pieces[pieceIdx];
678
+ if (pieceStickeringMask) {
679
+ const pieceInfo = this.kpuzzleFaceletInfo[orbitName][pieceIdx];
680
+ for (let faceletIdx = 0; faceletIdx < pieceInfo.length; faceletIdx++) {
681
+ const faceletStickeringMask = pieceStickeringMask.facelets[faceletIdx];
682
+ if (faceletStickeringMask) {
683
+ const faceletInfo = pieceInfo[faceletIdx];
684
+ const stickeringMask2 = typeof faceletStickeringMask === "string" ? faceletStickeringMask : faceletStickeringMask?.mask;
685
+ faceletInfo.facelet.material = axesInfo[faceletInfo.faceIdx].stickerMaterial[stickeringMask2];
686
+ const hintStickeringMask = typeof faceletStickeringMask === "string" ? stickeringMask2 : faceletStickeringMask.hintMask ?? stickeringMask2;
687
+ if (faceletInfo.hintFacelet) {
688
+ faceletInfo.hintFacelet.material = axesInfo[faceletInfo.faceIdx].hintStickerMaterial[hintStickeringMask];
689
+ }
690
+ }
691
+ }
692
+ }
693
+ }
694
+ }
695
+ if (this.scheduleRenderCallback) {
696
+ this.scheduleRenderCallback();
697
+ }
698
+ }
699
+ /** @deprecated */
700
+ experimentalUpdateOptions(options) {
701
+ if ("showMainStickers" in options) {
702
+ throw new Error("Unimplemented");
703
+ }
704
+ const showFoundation = options.showFoundation;
705
+ if (typeof showFoundation !== "undefined" && this.options.showFoundation !== showFoundation) {
706
+ this.options.showFoundation = showFoundation;
707
+ for (const foundation of this.experimentalFoundationMeshes) {
708
+ foundation.visible = showFoundation;
709
+ }
710
+ }
711
+ const hintFacelets = options.hintFacelets;
712
+ if (typeof hintFacelets !== "undefined" && this.options.hintFacelets !== hintFacelets && hintFaceletStyles[hintFacelets]) {
713
+ this.options.hintFacelets = hintFacelets;
714
+ for (const hintSticker of this.experimentalHintStickerMeshes) {
715
+ hintSticker.visible = hintFacelets === "floating";
716
+ }
717
+ this.scheduleRenderCallback();
718
+ }
719
+ const { experimentalStickeringMask } = options;
720
+ if (typeof experimentalStickeringMask !== "undefined") {
721
+ this.options.experimentalStickeringMask = experimentalStickeringMask;
722
+ this.setStickeringMask(experimentalStickeringMask);
723
+ this.scheduleRenderCallback();
724
+ }
725
+ const { faceletScale } = options;
726
+ if (typeof faceletScale !== "undefined") {
727
+ this.experimentalSetFaceletScale(faceletScale);
728
+ }
729
+ const { hintFaceletsElevation } = options;
730
+ if (typeof hintFaceletsElevation !== "undefined") {
731
+ this.setHintFaceletsElevation(hintFaceletsElevation);
732
+ }
733
+ }
734
+ onPositionChange(p) {
735
+ const reid333 = p.pattern;
736
+ for (const orbit in pieceDefs) {
737
+ const pieces = pieceDefs[orbit];
738
+ for (let i = 0; i < pieces.length; i++) {
739
+ const j = reid333.patternData[orbit].pieces[i];
740
+ this.pieces[orbit][j].matrix.copy(pieceDefs[orbit][i].matrix);
741
+ this.pieces[orbit][j].matrix.multiply(
742
+ orientationRotation[orbit][reid333.patternData[orbit].orientation[i]]
743
+ );
744
+ }
745
+ for (const moveProgress of p.movesInProgress) {
746
+ const move = moveProgress.move;
747
+ const turnNormal = axesInfo[familyToAxis[move.family]].vector;
748
+ const moveMatrix = new Matrix4().makeRotationAxis(
749
+ turnNormal,
750
+ -this.ease(moveProgress.fraction) * moveProgress.direction * move.amount * TAU / 4
751
+ );
752
+ const orbitTransformationData = this.kpuzzle.moveToTransformation(
753
+ move.modified({ amount: 1 })
754
+ ).transformationData[orbit];
755
+ const { permutation, orientationDelta } = orbitTransformationData;
756
+ for (let i = 0; i < pieces.length; i++) {
757
+ if (i !== permutation[i] || orientationDelta[i] !== 0) {
758
+ const j = reid333.patternData[orbit].pieces[i];
759
+ this.pieces[orbit][j].matrix.premultiply(moveMatrix);
760
+ }
761
+ }
762
+ }
763
+ }
764
+ this.scheduleRenderCallback();
765
+ }
766
+ // TODO: Always create (but sometimes hide parts) so we can show them later,
767
+ // or (better) support creating puzzle parts on demand.
768
+ createCubie(orbit, orbitFacelets, piece, orbitPieceIdx) {
769
+ const cubieFaceletInfo = [];
770
+ orbitFacelets.push(cubieFaceletInfo);
771
+ const cubie = new Group();
772
+ if (this.options.showFoundation) {
773
+ const foundation = this.createCubieFoundation();
774
+ cubie.add(foundation);
775
+ this.experimentalFoundationMeshes.push(foundation);
776
+ }
777
+ for (let i = 0; i < piece.stickerFaces.length; i++) {
778
+ const sticker = this.createSticker(
779
+ axesInfo[cubieStickerOrder[i]],
780
+ axesInfo[piece.stickerFaces[i]],
781
+ false
782
+ );
783
+ const faceletInfo = {
784
+ faceIdx: piece.stickerFaces[i],
785
+ facelet: sticker
786
+ };
787
+ cubie.add(sticker);
788
+ if (this.options.hintFacelets === "floating") {
789
+ const hintSticker = this.createSticker(
790
+ axesInfo[cubieStickerOrder[i]],
791
+ axesInfo[piece.stickerFaces[i]],
792
+ true
793
+ );
794
+ cubie.add(hintSticker);
795
+ faceletInfo.hintFacelet = hintSticker;
796
+ this.experimentalHintStickerMeshes.push(hintSticker);
797
+ }
798
+ if (this.options.experimentalStickeringMask?.specialBehaviour === "picture" && pictureStickerCoords[orbit] && pictureStickerCoords[orbit][orbitPieceIdx] && pictureStickerCoords[orbit][orbitPieceIdx][i]) {
799
+ const [rotate, offsetX, offsetY] = pictureStickerCoords[orbit][orbitPieceIdx][i];
800
+ void (async () => {
801
+ const addImageSticker = async (hint) => {
802
+ const texture = await (hint ? this.hintSprite : this.sprite);
803
+ const mesh = this.createSticker(
804
+ axesInfo[cubieStickerOrder[i]],
805
+ axesInfo[piece.stickerFaces[i]],
806
+ hint
807
+ );
808
+ mesh.material = new MeshBasicMaterial({
809
+ map: texture,
810
+ side: hint ? BackSide : DoubleSide,
811
+ transparent: true
812
+ });
813
+ const x1 = offsetX / 12;
814
+ const x2 = (offsetX + 1) / 12;
815
+ const y1 = offsetY / 9;
816
+ const y2 = (offsetY + 1) / 9;
817
+ let v1 = new Vector2(x1, y1);
818
+ let v2 = new Vector2(x1, y2);
819
+ let v3 = new Vector2(x2, y2);
820
+ let v4 = new Vector2(x2, y1);
821
+ switch (rotate) {
822
+ case 1: {
823
+ [v1, v2, v3, v4] = [v2, v3, v4, v1];
824
+ break;
825
+ }
826
+ case 2: {
827
+ [v1, v2, v3, v4] = [v3, v4, v1, v2];
828
+ break;
829
+ }
830
+ case 3: {
831
+ [v1, v2, v3, v4] = [v4, v1, v2, v3];
832
+ break;
833
+ }
834
+ }
835
+ mesh.geometry.setAttribute(
836
+ "uv",
837
+ new BufferAttribute(
838
+ new Float32Array([
839
+ v3.x,
840
+ v3.y,
841
+ v2.x,
842
+ v2.y,
843
+ v4.x,
844
+ v4.y,
845
+ v2.x,
846
+ v2.y,
847
+ v1.x,
848
+ v1.y,
849
+ v4.x,
850
+ v4.y
851
+ ]),
852
+ 2
853
+ )
854
+ );
855
+ cubie.add(mesh);
856
+ };
857
+ void addImageSticker(true);
858
+ void addImageSticker(false);
859
+ })();
860
+ }
861
+ cubieFaceletInfo.push(faceletInfo);
862
+ }
863
+ cubie.matrix.copy(piece.matrix);
864
+ cubie.matrixAutoUpdate = false;
865
+ this.add(cubie);
866
+ return cubie;
867
+ }
868
+ // TODO: Support creating only the outward-facing parts?
869
+ createCubieFoundation() {
870
+ const box = sharedCubieFoundationGeometry();
871
+ return new Mesh(
872
+ box,
873
+ this.options.experimentalStickeringMask?.specialBehaviour === "picture" ? blackMesh : blackTranslucentMesh
874
+ );
875
+ }
876
+ createSticker(posAxisInfo, materialAxisInfo, isHint) {
877
+ const geo = this.options.experimentalStickeringMask?.specialBehaviour === "picture" ? newStickerGeometry() : isHint ? this.#sharedHintStickerGeometry() : sharedStickerGeometry();
878
+ const stickerMesh = new Mesh(
879
+ geo,
880
+ isHint ? materialAxisInfo.hintStickerMaterial.regular : materialAxisInfo.stickerMaterial.regular
881
+ );
882
+ stickerMesh.setRotationFromEuler(posAxisInfo.fromZ);
883
+ stickerMesh.position.copy(posAxisInfo.vector);
884
+ const elevation = (() => {
885
+ if (!isHint) {
886
+ return cubieDimensions.stickerElevation;
887
+ }
888
+ if (typeof this.options.hintFaceletsElevation === "number") {
889
+ return this.options.hintFaceletsElevation;
890
+ }
891
+ if (this.options.experimentalStickeringMask?.specialBehaviour === "picture") {
892
+ return EXPERIMENTAL_PICTURE_CUBE_HINT_ELEVATION;
893
+ }
894
+ return cubieDimensions.defaultHintStickerElevation;
895
+ })();
896
+ if (isHint) {
897
+ this.#lastHintStickerElevation = elevation;
898
+ }
899
+ const scale = getFaceletScale(this.options);
900
+ stickerMesh.scale.setX(scale);
901
+ stickerMesh.scale.setY(scale);
902
+ stickerMesh.translateZ(elevation - 1);
903
+ return stickerMesh;
904
+ }
905
+ /** @deprecated */
906
+ experimentalSetFoundationOpacity(opacity) {
907
+ this.experimentalFoundationMeshes[0].material.opacity = opacity;
908
+ }
909
+ /** @deprecated */
910
+ experimentalSetFaceletScale(faceletScale) {
911
+ this.options.faceletScale = faceletScale;
912
+ for (const orbitInfo of Object.values(this.kpuzzleFaceletInfo)) {
913
+ for (const pieceInfo of orbitInfo) {
914
+ for (const faceletInfo of pieceInfo) {
915
+ const scale = getFaceletScale(this.options);
916
+ faceletInfo.facelet.scale.setX(scale);
917
+ faceletInfo.facelet.scale.setY(scale);
918
+ faceletInfo.hintFacelet?.scale.setX(scale);
919
+ faceletInfo.hintFacelet?.scale.setY(scale);
920
+ }
921
+ }
922
+ }
923
+ }
924
+ // /** @deprecated */
925
+ // experimentalSetCenterStickerWidth(width: number): void {
926
+ // for (const orbitInfo of [this.kpuzzleFaceletInfo["CENTERS"]]) {
927
+ // for (const pieceInfo of orbitInfo) {
928
+ // for (const faceletInfo of pieceInfo) {
929
+ // faceletInfo.facelet.scale.setScalar(
930
+ // width / getStickerScale(this.options),
931
+ // );
932
+ // // faceletInfo.facelet.setRotationFromAxisAngle(new Vector3(0, 1, 0), 0);
933
+ // // faceletInfo.facelet.rotateOnAxis(new Vector3(1, 0, 1), TAU / 6);
934
+ // }
935
+ // }
936
+ // }
937
+ // }
938
+ ease(fraction) {
939
+ return smootherStep(fraction);
940
+ }
941
+ };
942
+
943
+ // src/cubing/twisty/views/3D/puzzles/PG3D.ts
944
+ import { DoubleSide as DoubleSide2, FrontSide as FrontSide2 } from "three/src/constants.js";
945
+ import { BufferAttribute as BufferAttribute2 } from "three/src/core/BufferAttribute.js";
946
+ import { BufferGeometry as BufferGeometry2 } from "three/src/core/BufferGeometry.js";
947
+ import { Object3D as Object3D2 } from "three/src/core/Object3D.js";
948
+ import { MeshBasicMaterial as MeshBasicMaterial2 } from "three/src/materials/MeshBasicMaterial.js";
949
+ import { Color as Color2 } from "three/src/math/Color.js";
950
+ import { Vector3 as Vector32 } from "three/src/math/Vector3.js";
951
+ import { Group as Group2 } from "three/src/objects/Group.js";
952
+ import { Mesh as Mesh2 } from "three/src/objects/Mesh.js";
953
+ var foundationMaterial = new MeshBasicMaterial2({
954
+ side: DoubleSide2,
955
+ color: 0
956
+ });
957
+ var invisMaterial = new MeshBasicMaterial2({
958
+ visible: false
959
+ });
960
+ var basicStickerMaterial = new MeshBasicMaterial2({
961
+ vertexColors: true
962
+ });
963
+ function dist(coords, a, b) {
964
+ return Math.hypot(
965
+ coords[3 * a] - coords[3 * b],
966
+ coords[3 * a + 1] - coords[3 * b + 1],
967
+ coords[3 * a + 2] - coords[3 * b + 2]
968
+ );
969
+ }
970
+ function triarea(coords, a, b, c) {
971
+ const ab = dist(coords, a, b);
972
+ const bc = dist(coords, b, c);
973
+ const ac = dist(coords, a, c);
974
+ const p = (ab + bc + ac) / 2;
975
+ return Math.sqrt(p * (p - ab) * (p - bc) * (p - ac));
976
+ }
977
+ function polyarea(coords) {
978
+ let sum = 0;
979
+ for (let i = 2; 3 * i < coords.length; i++) {
980
+ sum += triarea(coords, 0, 1, i);
981
+ }
982
+ return sum;
983
+ }
984
+ function normalize(r2) {
985
+ const m = Math.hypot(r2[0], r2[1], r2[2]);
986
+ r2[0] /= m;
987
+ r2[1] /= m;
988
+ r2[2] /= m;
989
+ return r2;
990
+ }
991
+ function cross(a, b) {
992
+ const r2 = new Array(3);
993
+ r2[0] = a[1] * b[2] - a[2] * b[1];
994
+ r2[1] = a[2] * b[0] - a[0] * b[2];
995
+ r2[2] = a[0] * b[1] - a[1] * b[0];
996
+ return r2;
997
+ }
998
+ function normal(c) {
999
+ const a = [c[3] - c[0], c[4] - c[1], c[5] - c[2]];
1000
+ const b = [c[6] - c[3], c[7] - c[4], c[8] - c[5]];
1001
+ const r2 = cross(a, b);
1002
+ return normalize(r2);
1003
+ }
1004
+ function trimEdges(face2, tr) {
1005
+ const r2 = [];
1006
+ const A = new Array(3);
1007
+ const B = new Array(3);
1008
+ for (let iter = 1; iter < 10; iter++) {
1009
+ for (let i = 0; i < face2.length; i += 3) {
1010
+ const pi = (i + face2.length - 3) % face2.length;
1011
+ const ni = (i + 3) % face2.length;
1012
+ for (let k = 0; k < 3; k++) {
1013
+ A[k] = face2[pi + k] - face2[i + k];
1014
+ B[k] = face2[ni + k] - face2[i + k];
1015
+ }
1016
+ const alen = Math.hypot(A[0], A[1], A[2]);
1017
+ const blen = Math.hypot(B[0], B[1], B[2]);
1018
+ for (let k = 0; k < 3; k++) {
1019
+ A[k] /= alen;
1020
+ B[k] /= blen;
1021
+ }
1022
+ const d = A[0] * B[0] + A[1] * B[1] + A[2] * B[2];
1023
+ const m = tr / Math.sqrt(1 - d * d);
1024
+ for (let k = 0; k < 3; k++) {
1025
+ r2[i + k] = face2[i + k] + (A[k] + B[k]) * m;
1026
+ }
1027
+ }
1028
+ let good = true;
1029
+ for (let i = 0; good && i < r2.length; i += 3) {
1030
+ const ni = (i + 3) % face2.length;
1031
+ let t2 = 0;
1032
+ for (let k = 0; k < 3; k++) {
1033
+ const a = face2[ni + k] - face2[i + k];
1034
+ const b = r2[ni + k] - r2[i + k];
1035
+ t2 += a * b;
1036
+ }
1037
+ if (t2 <= 0) {
1038
+ good = false;
1039
+ }
1040
+ }
1041
+ if (good) {
1042
+ return r2;
1043
+ }
1044
+ tr /= 2;
1045
+ }
1046
+ return face2;
1047
+ }
1048
+ var Filler = class {
1049
+ constructor(sz, tm) {
1050
+ this.sz = sz;
1051
+ this.tm = tm;
1052
+ this.vertices = new Float32Array(9 * sz);
1053
+ this.uvs = void 0;
1054
+ this.colors = new Uint8Array(18 * sz);
1055
+ this.ind = new Uint8Array(sz);
1056
+ this.pos = 0;
1057
+ this.ipos = 0;
1058
+ }
1059
+ sz;
1060
+ tm;
1061
+ pos;
1062
+ ipos;
1063
+ vertices;
1064
+ colors;
1065
+ uvs;
1066
+ ind;
1067
+ add(pt, i, c) {
1068
+ this.vertices[this.pos] = pt[3 * i + 0];
1069
+ this.vertices[this.pos + 1] = pt[3 * i + 1];
1070
+ this.vertices[this.pos + 2] = pt[3 * i + 2];
1071
+ this.colors[this.pos] = c >> 16;
1072
+ this.colors[this.pos + 1] = c >> 8 & 255;
1073
+ this.colors[this.pos + 2] = c & 255;
1074
+ this.pos += 3;
1075
+ }
1076
+ addUncolored(pt, i) {
1077
+ this.vertices[this.pos] = pt[3 * i + 0];
1078
+ this.vertices[this.pos + 1] = pt[3 * i + 1];
1079
+ this.vertices[this.pos + 2] = pt[3 * i + 2];
1080
+ this.pos += 3;
1081
+ }
1082
+ setind(i) {
1083
+ this.ind[this.ipos++] = i;
1084
+ }
1085
+ makePoly(coords, color, ind) {
1086
+ const ncoords = coords;
1087
+ for (let g = 1; 3 * (g + 1) < ncoords.length; g++) {
1088
+ this.add(ncoords, 0, color);
1089
+ this.add(ncoords, g, color);
1090
+ this.add(ncoords, g + 1, color);
1091
+ this.setind(ind);
1092
+ }
1093
+ }
1094
+ setAttributes(geo) {
1095
+ geo.setAttribute("position", new BufferAttribute2(this.vertices, 3));
1096
+ const sa2 = this.colors.subarray(0, 9 * this.sz);
1097
+ geo.setAttribute("color", new BufferAttribute2(sa2, 3, true));
1098
+ }
1099
+ makeGroups(geo) {
1100
+ geo.clearGroups();
1101
+ for (let i = 0; i < this.ipos; ) {
1102
+ const si = i++;
1103
+ const iv = this.ind[si];
1104
+ while (this.ind[i] === iv) {
1105
+ i++;
1106
+ }
1107
+ geo.addGroup(3 * si, 3 * (i - si), iv);
1108
+ }
1109
+ }
1110
+ saveOriginalColors() {
1111
+ this.colors.copyWithin(this.pos, 0, this.pos);
1112
+ }
1113
+ };
1114
+ var StickerDef = class {
1115
+ origColor;
1116
+ origColorStickeringMask;
1117
+ faceColor;
1118
+ texturePtr = void 0;
1119
+ twistVal = -1;
1120
+ stickerStart;
1121
+ stickerEnd;
1122
+ hintStart;
1123
+ hintEnd;
1124
+ foundationStart;
1125
+ foundationEnd;
1126
+ isDup;
1127
+ faceNum;
1128
+ constructor(filler, stickerDat, trim, options) {
1129
+ this.isDup = !!stickerDat.isDup;
1130
+ this.faceNum = stickerDat.face;
1131
+ this.stickerStart = filler.ipos;
1132
+ const sdColor = new Color2(stickerDat.color).getHex();
1133
+ this.origColor = sdColor;
1134
+ this.origColorStickeringMask = sdColor;
1135
+ if (options?.stickeringMask) {
1136
+ this.setStickeringMask(filler, options.stickeringMask);
1137
+ }
1138
+ this.faceColor = sdColor;
1139
+ const coords = this.stickerCoords(stickerDat.coords, trim);
1140
+ filler.makePoly(coords, this.faceColor, this.isDup ? 4 : 0);
1141
+ this.stickerEnd = filler.ipos;
1142
+ }
1143
+ stickerCoords(coords, trim) {
1144
+ return trimEdges(coords.slice(), trim);
1145
+ }
1146
+ hintCoords(coords, hintStickerHeightScale, trim, normal2) {
1147
+ coords = this.stickerCoords(coords, trim);
1148
+ normal2 = normal2.slice();
1149
+ for (let i = 0; i < 3; i++) {
1150
+ normal2[i] *= 0.5 * hintStickerHeightScale;
1151
+ }
1152
+ const hCoords = new Array(coords.length);
1153
+ for (let i = 0; 3 * i < coords.length; i++) {
1154
+ const j = coords.length / 3 - 1 - i;
1155
+ hCoords[3 * i] = coords[3 * j] + normal2[0];
1156
+ hCoords[3 * i + 1] = coords[3 * j + 1] + normal2[1];
1157
+ hCoords[3 * i + 2] = coords[3 * j + 2] + normal2[2];
1158
+ }
1159
+ return hCoords;
1160
+ }
1161
+ foundationCoords(coords) {
1162
+ const ncoords = coords.slice();
1163
+ for (let i = 0; i < coords.length; i++) {
1164
+ ncoords[i] = coords[i] * 0.999;
1165
+ }
1166
+ return ncoords;
1167
+ }
1168
+ addHint(filler, stickerDat, hintStickers, hintStickerHeightScale, trim, normal2) {
1169
+ this.hintStart = filler.ipos;
1170
+ const coords = this.hintCoords(
1171
+ stickerDat.coords,
1172
+ hintStickerHeightScale,
1173
+ trim,
1174
+ normal2
1175
+ );
1176
+ filler.makePoly(
1177
+ coords,
1178
+ this.faceColor,
1179
+ hintStickers && !this.isDup ? 2 : 4
1180
+ );
1181
+ this.hintEnd = filler.ipos;
1182
+ }
1183
+ addFoundation(filler, stickerDat, black) {
1184
+ this.foundationStart = filler.ipos;
1185
+ const coords = this.foundationCoords(stickerDat.coords);
1186
+ filler.makePoly(coords, black, this.isDup ? 4 : 6);
1187
+ this.foundationEnd = filler.ipos;
1188
+ }
1189
+ setHintStickers(filler, hintStickers) {
1190
+ const indv = this.isDup || !hintStickers ? 4 : 2;
1191
+ for (let i = this.hintStart; i < this.hintEnd; i++) {
1192
+ filler.ind[i] = indv | filler.ind[i] & 1;
1193
+ }
1194
+ }
1195
+ setStickeringMask(filler, faceletMeshStickeringMask) {
1196
+ let c = 0;
1197
+ switch (faceletMeshStickeringMask) {
1198
+ case "regular": {
1199
+ c = this.origColor;
1200
+ break;
1201
+ }
1202
+ case "dim": {
1203
+ if (this.origColor === 16777215) {
1204
+ c = 14540253;
1205
+ } else {
1206
+ c = new Color2(this.origColor).multiplyScalar(0.5).getHex();
1207
+ }
1208
+ break;
1209
+ }
1210
+ case "oriented": {
1211
+ c = 4513228;
1212
+ break;
1213
+ }
1214
+ case "experimentalOriented2": {
1215
+ c = 16776618;
1216
+ break;
1217
+ }
1218
+ case "ignored": {
1219
+ c = 4473924;
1220
+ break;
1221
+ }
1222
+ case "mystery": {
1223
+ c = 15911883;
1224
+ break;
1225
+ }
1226
+ case "invisible":
1227
+ c = this.origColor;
1228
+ }
1229
+ this.origColorStickeringMask = c;
1230
+ for (let i = 9 * this.stickerStart; i < 9 * this.stickerEnd; i += 3) {
1231
+ filler.colors[filler.pos + i] = c >> 16;
1232
+ filler.colors[filler.pos + i + 1] = c >> 8 & 255;
1233
+ filler.colors[filler.pos + i + 2] = c & 255;
1234
+ }
1235
+ for (let i = 9 * this.hintStart; i < 9 * this.hintEnd; i += 3) {
1236
+ filler.colors[filler.pos + i] = c >> 16;
1237
+ filler.colors[filler.pos + i + 1] = c >> 8 & 255;
1238
+ filler.colors[filler.pos + i + 2] = c & 255;
1239
+ }
1240
+ this.setHintStickers(
1241
+ filler,
1242
+ faceletMeshStickeringMask !== "invisible" && !this.isDup
1243
+ );
1244
+ }
1245
+ addUVs(filler) {
1246
+ const uvs = filler.uvs;
1247
+ const vert = filler.vertices;
1248
+ const coords = new Array(3);
1249
+ for (let i = 3 * this.stickerStart; i < 3 * this.stickerEnd; i++) {
1250
+ coords[0] = vert[3 * i];
1251
+ coords[1] = vert[3 * i + 1];
1252
+ coords[2] = vert[3 * i + 2];
1253
+ const uv = filler.tm.getuv(this.faceNum, coords);
1254
+ uvs[2 * i] = uv[0];
1255
+ uvs[2 * i + 1] = uv[1];
1256
+ }
1257
+ for (let i = 3 * this.hintStart; i < 3 * this.hintEnd; i++) {
1258
+ coords[0] = vert[3 * i];
1259
+ coords[1] = vert[3 * i + 1];
1260
+ coords[2] = vert[3 * i + 2];
1261
+ const uv = filler.tm.getuv(this.faceNum, coords);
1262
+ uvs[2 * i] = uv[0];
1263
+ uvs[2 * i + 1] = uv[1];
1264
+ }
1265
+ }
1266
+ setTexture(filler, sd) {
1267
+ if (this.texturePtr === sd) {
1268
+ return 0;
1269
+ }
1270
+ this.texturePtr = sd;
1271
+ const sz = 6 * filler.sz;
1272
+ filler.uvs.copyWithin(
1273
+ 6 * this.stickerStart,
1274
+ 6 * sd.stickerStart + sz,
1275
+ 6 * sd.stickerEnd + sz
1276
+ );
1277
+ filler.uvs.copyWithin(
1278
+ 6 * this.hintStart,
1279
+ // TODO: refactor to avoid non-null-assertion
1280
+ 6 * sd.hintStart + sz,
1281
+ // TODO: refactor to avoid non-null-assertion
1282
+ 6 * sd.hintEnd + sz
1283
+ // TODO: refactor to avoid non-null-assertion
1284
+ );
1285
+ return 1;
1286
+ }
1287
+ setColor(filler, sd) {
1288
+ const c = sd.origColorStickeringMask;
1289
+ if (this.faceColor !== c) {
1290
+ this.faceColor = c;
1291
+ const sz = filler.pos;
1292
+ filler.colors.copyWithin(
1293
+ 9 * this.stickerStart,
1294
+ 9 * sd.stickerStart + sz,
1295
+ 9 * sd.stickerEnd + sz
1296
+ );
1297
+ filler.colors.copyWithin(
1298
+ 9 * this.hintStart,
1299
+ // TODO: refactor to avoid non-null-assertion
1300
+ 9 * sd.hintStart + sz,
1301
+ // TODO: refactor to avoid non-null-assertion
1302
+ 9 * sd.hintEnd + sz
1303
+ // TODO: refactor to avoid non-null-assertion
1304
+ );
1305
+ return 1;
1306
+ } else {
1307
+ return 0;
1308
+ }
1309
+ }
1310
+ };
1311
+ var HitPlaneDef = class {
1312
+ cubie;
1313
+ geo;
1314
+ constructor(hitface, tm, stickerDat) {
1315
+ this.cubie = new Group2();
1316
+ const coords = hitface.coords;
1317
+ const filler = new Filler(coords.length / 3 - 2, tm);
1318
+ for (let g = 1; 3 * g + 3 < coords.length; g++) {
1319
+ filler.addUncolored(coords, 0);
1320
+ filler.addUncolored(coords, g);
1321
+ filler.addUncolored(coords, g + 1);
1322
+ }
1323
+ this.geo = new BufferGeometry2();
1324
+ filler.setAttributes(this.geo);
1325
+ const obj = new Mesh2(this.geo, invisMaterial);
1326
+ obj.userData["quantumMove"] = stickerDat.notationMapper.notationToExternal(
1327
+ new Move(hitface.name)
1328
+ );
1329
+ this.cubie.scale.setScalar(0.99);
1330
+ this.cubie.add(obj);
1331
+ }
1332
+ };
1333
+ var AxisInfo2 = class {
1334
+ axis;
1335
+ order;
1336
+ constructor(axisDat) {
1337
+ const vec = axisDat.coordinates;
1338
+ this.axis = new Vector32(vec[0], vec[1], vec[2]);
1339
+ this.order = axisDat.order;
1340
+ }
1341
+ };
1342
+ var DEFAULT_COLOR_FRACTION = 0.71;
1343
+ var PG_SCALE = 0.5;
1344
+ var PG3D = class extends Object3D2 {
1345
+ constructor(scheduleRenderCallback, kpuzzle, stickerDat, enableFoundationOpt = false, enableHintStickersOpt = false, hintStickerHeightScale = 1, faceletScale = 1, params = {}) {
1346
+ super();
1347
+ this.scheduleRenderCallback = scheduleRenderCallback;
1348
+ this.kpuzzle = kpuzzle;
1349
+ this.stickerDat = stickerDat;
1350
+ this.faceletScale = faceletScale;
1351
+ this.params = params;
1352
+ if (stickerDat.stickers.length === 0) {
1353
+ throw Error("Reuse of stickerdat from pg; please don't do that.");
1354
+ }
1355
+ this.hintMaterial = new MeshBasicMaterial2({
1356
+ vertexColors: true,
1357
+ transparent: true,
1358
+ opacity: 0.5
1359
+ });
1360
+ this.hintMaterialDisposable = true;
1361
+ this.stickerMaterial = basicStickerMaterial;
1362
+ this.stickerMaterialDisposable = false;
1363
+ this.axesInfo = {};
1364
+ const axesDef = this.stickerDat.axis;
1365
+ for (const axis of axesDef) {
1366
+ this.axesInfo[axis.quantumMove.family] = new AxisInfo2(axis);
1367
+ }
1368
+ const stickers = this.stickerDat.stickers;
1369
+ this.stickers = {};
1370
+ this.materialArray1 = new Array(8);
1371
+ this.materialArray2 = new Array(8);
1372
+ this.showFoundation(enableFoundationOpt);
1373
+ enableFoundationOpt = true;
1374
+ let triangleCount = 0;
1375
+ const multiplier = 3;
1376
+ for (const sticker of stickers) {
1377
+ const sides = sticker.coords.length / 3;
1378
+ triangleCount += multiplier * (sides - 2);
1379
+ }
1380
+ const filler = new Filler(triangleCount, stickerDat.textureMapper);
1381
+ const black = 0;
1382
+ const normals = [];
1383
+ let totArea = 0;
1384
+ for (const f of stickerDat.faces) {
1385
+ normals.push(normal(f.coords));
1386
+ totArea += polyarea(f.coords);
1387
+ }
1388
+ const colorfrac = faceletScale !== "auto" ? faceletScale * faceletScale : DEFAULT_COLOR_FRACTION;
1389
+ let nonDupStickers = 0;
1390
+ for (const sticker of stickers) {
1391
+ if (!sticker.isDup) {
1392
+ nonDupStickers++;
1393
+ }
1394
+ }
1395
+ const trim = Math.sqrt(totArea / nonDupStickers) * (1 - Math.sqrt(colorfrac)) / 2;
1396
+ for (const sticker of stickers) {
1397
+ const orbit = sticker.orbit;
1398
+ const ord = sticker.ord;
1399
+ const ori = sticker.ori;
1400
+ if (!this.stickers[orbit]) {
1401
+ this.stickers[orbit] = [];
1402
+ }
1403
+ if (!this.stickers[orbit][ori]) {
1404
+ this.stickers[orbit][ori] = [];
1405
+ }
1406
+ const options = {};
1407
+ if (params.stickeringMask) {
1408
+ options.stickeringMask = getFaceletStickeringMask(
1409
+ params.stickeringMask,
1410
+ orbit,
1411
+ ord,
1412
+ ori,
1413
+ false
1414
+ );
1415
+ }
1416
+ const stickerdef = new StickerDef(filler, sticker, trim, options);
1417
+ this.stickers[orbit][ori][ord] = stickerdef;
1418
+ }
1419
+ this.showHintStickers = enableHintStickersOpt;
1420
+ enableHintStickersOpt = true;
1421
+ for (const sticker of stickers) {
1422
+ const orbit = sticker.orbit;
1423
+ const ord = sticker.ord;
1424
+ const ori = sticker.ori;
1425
+ this.stickers[orbit][ori][ord].addHint(
1426
+ filler,
1427
+ sticker,
1428
+ enableHintStickersOpt,
1429
+ hintStickerHeightScale,
1430
+ trim,
1431
+ normals[sticker.face]
1432
+ );
1433
+ }
1434
+ this.foundationBound = filler.ipos;
1435
+ for (const sticker of stickers) {
1436
+ const orbit = sticker.orbit;
1437
+ const ord = sticker.ord;
1438
+ const ori = sticker.ori;
1439
+ if (enableFoundationOpt) {
1440
+ this.stickers[orbit][ori][ord].addFoundation(filler, sticker, black);
1441
+ }
1442
+ }
1443
+ const fixedGeo = new BufferGeometry2();
1444
+ filler.setAttributes(fixedGeo);
1445
+ filler.makeGroups(fixedGeo);
1446
+ const obj = new Mesh2(fixedGeo, this.materialArray1);
1447
+ obj.scale.set(PG_SCALE, PG_SCALE, PG_SCALE);
1448
+ this.add(obj);
1449
+ const obj2 = new Mesh2(fixedGeo, this.materialArray2);
1450
+ obj2.scale.set(PG_SCALE, PG_SCALE, PG_SCALE);
1451
+ this.add(obj2);
1452
+ const hitfaces = this.stickerDat.faces;
1453
+ this.movingObj = obj2;
1454
+ this.fixedGeo = fixedGeo;
1455
+ this.filler = filler;
1456
+ for (const hitface of hitfaces) {
1457
+ const facedef = new HitPlaneDef(
1458
+ hitface,
1459
+ stickerDat.textureMapper,
1460
+ this.stickerDat
1461
+ );
1462
+ facedef.cubie.scale.set(PG_SCALE, PG_SCALE, PG_SCALE);
1463
+ this.add(facedef.cubie);
1464
+ this.controlTargets.push(facedef.cubie.children[0]);
1465
+ }
1466
+ filler.saveOriginalColors();
1467
+ stickerDat.stickers = [];
1468
+ this.updateMaterialArrays();
1469
+ }
1470
+ scheduleRenderCallback;
1471
+ kpuzzle;
1472
+ stickerDat;
1473
+ faceletScale;
1474
+ params;
1475
+ stickers;
1476
+ axesInfo;
1477
+ stickerTargets = [];
1478
+ controlTargets = [];
1479
+ movingObj;
1480
+ filler;
1481
+ foundationBound;
1482
+ // before this: colored; after: black
1483
+ fixedGeo;
1484
+ lastPos;
1485
+ lastMoveTransformationData;
1486
+ hintMaterial;
1487
+ stickerMaterial;
1488
+ materialArray1;
1489
+ materialArray2;
1490
+ textured = false;
1491
+ showHintStickers = false;
1492
+ showFoundations = false;
1493
+ hintMaterialDisposable;
1494
+ stickerMaterialDisposable;
1495
+ #pendingStickeringUpdate = false;
1496
+ dispose() {
1497
+ if (this.fixedGeo) {
1498
+ this.fixedGeo.dispose();
1499
+ }
1500
+ if (this.stickerMaterialDisposable) {
1501
+ this.stickerMaterial.dispose();
1502
+ this.stickerMaterial = basicStickerMaterial;
1503
+ this.stickerMaterialDisposable = false;
1504
+ }
1505
+ if (this.hintMaterialDisposable) {
1506
+ this.hintMaterial.dispose();
1507
+ this.hintMaterial = basicStickerMaterial;
1508
+ this.hintMaterialDisposable = false;
1509
+ }
1510
+ }
1511
+ experimentalGetStickerTargets() {
1512
+ return this.stickerTargets;
1513
+ }
1514
+ experimentalGetControlTargets() {
1515
+ return this.controlTargets;
1516
+ }
1517
+ #isValidMove(move) {
1518
+ try {
1519
+ this.kpuzzle.moveToTransformation(move);
1520
+ return true;
1521
+ } catch (_) {
1522
+ return false;
1523
+ }
1524
+ }
1525
+ getClosestMoveToAxis(point, transformations) {
1526
+ let closestMove = null;
1527
+ let closestMoveDotProduct = 0;
1528
+ let modify = (m) => m;
1529
+ switch (transformations.depth) {
1530
+ case "secondSlice": {
1531
+ modify = (m) => m.modified({ innerLayer: 2 });
1532
+ break;
1533
+ }
1534
+ case "rotation": {
1535
+ modify = (m) => m.modified({ family: `${m.family}v` });
1536
+ break;
1537
+ }
1538
+ }
1539
+ for (const axis of this.stickerDat.axis) {
1540
+ const product = point.dot(new Vector32(...axis.coordinates));
1541
+ if (product > closestMoveDotProduct) {
1542
+ const modified = this.stickerDat.notationMapper.notationToExternal(
1543
+ modify(axis.quantumMove)
1544
+ );
1545
+ if (!modified) {
1546
+ continue;
1547
+ }
1548
+ console.log(modified.family);
1549
+ if (modified.family === "T" && transformations.depth === "none") {
1550
+ continue;
1551
+ }
1552
+ if (this.#isValidMove(modified)) {
1553
+ closestMoveDotProduct = product;
1554
+ closestMove = modified;
1555
+ }
1556
+ }
1557
+ }
1558
+ if (!closestMove) {
1559
+ return null;
1560
+ }
1561
+ if (transformations.invert) {
1562
+ closestMove = closestMove.invert();
1563
+ }
1564
+ const order = this.kpuzzle.moveToTransformation(closestMove).repetitionOrder();
1565
+ return { move: closestMove, order };
1566
+ }
1567
+ setStickeringMask(stickeringMask) {
1568
+ this.params.stickeringMask = stickeringMask;
1569
+ if (stickeringMask.specialBehaviour !== "picture") {
1570
+ for (const orbitDefinition of this.kpuzzle.definition.orbits) {
1571
+ const { numPieces, numOrientations } = orbitDefinition;
1572
+ for (let pieceIdx = 0; pieceIdx < numPieces; pieceIdx++) {
1573
+ for (let faceletIdx = 0; faceletIdx < numOrientations; faceletIdx++) {
1574
+ const faceletStickeringMask = getFaceletStickeringMask(
1575
+ stickeringMask,
1576
+ orbitDefinition.orbitName,
1577
+ pieceIdx,
1578
+ faceletIdx,
1579
+ false
1580
+ );
1581
+ const stickerDef = this.stickers[orbitDefinition.orbitName][faceletIdx][pieceIdx];
1582
+ if (this.textured && this.hintMaterialDisposable && faceletStickeringMask === "invisible") {
1583
+ } else {
1584
+ stickerDef.setStickeringMask(this.filler, faceletStickeringMask);
1585
+ }
1586
+ }
1587
+ }
1588
+ }
1589
+ }
1590
+ this.#pendingStickeringUpdate = true;
1591
+ if (this.lastPos) {
1592
+ this.onPositionChange(this.lastPos);
1593
+ }
1594
+ }
1595
+ onPositionChange(p) {
1596
+ const { pattern } = p;
1597
+ this.movingObj.rotation.set(0, 0, 0);
1598
+ let colormods = 0;
1599
+ const filler = this.filler;
1600
+ const ind = filler.ind;
1601
+ if (!this.lastPos || this.#pendingStickeringUpdate || !this.lastPos.pattern.isIdentical(pattern)) {
1602
+ for (const orbit in this.stickers) {
1603
+ const pieces = this.stickers[orbit];
1604
+ const pos2 = pattern.patternData[orbit];
1605
+ const orin = pieces.length;
1606
+ if (orin === 1) {
1607
+ const pieces2 = pieces[0];
1608
+ for (let i = 0; i < pieces2.length; i++) {
1609
+ const ni = pos2.pieces[i];
1610
+ if (this.textured) {
1611
+ colormods += pieces2[i].setTexture(filler, pieces2[ni]);
1612
+ } else {
1613
+ colormods += pieces2[i].setColor(filler, pieces2[ni]);
1614
+ }
1615
+ }
1616
+ } else {
1617
+ for (let ori = 0; ori < orin; ori++) {
1618
+ const pieces2 = pieces[ori];
1619
+ for (let i = 0; i < pieces2.length; i++) {
1620
+ const nori = (ori + orin - pos2.orientation[i]) % orin;
1621
+ const ni = pos2.pieces[i];
1622
+ if (this.textured) {
1623
+ colormods += pieces2[i].setTexture(filler, pieces[nori][ni]);
1624
+ } else {
1625
+ colormods += pieces2[i].setColor(filler, pieces[nori][ni]);
1626
+ }
1627
+ }
1628
+ }
1629
+ }
1630
+ }
1631
+ this.lastPos = p;
1632
+ }
1633
+ let vismods = 0;
1634
+ for (const moveProgress of p.movesInProgress) {
1635
+ const externalMove = moveProgress.move;
1636
+ const unswizzled = this.stickerDat.unswizzle(externalMove);
1637
+ if (!unswizzled) {
1638
+ return;
1639
+ }
1640
+ const move = externalMove;
1641
+ let quantumTransformation;
1642
+ try {
1643
+ quantumTransformation = this.kpuzzle.moveToTransformation(
1644
+ move.modified({ amount: 1 })
1645
+ );
1646
+ } catch (e) {
1647
+ const move1 = this.stickerDat.notationMapper.notationToInternal(move);
1648
+ if (move1) {
1649
+ const move2 = this.stickerDat.notationMapper.notationToExternal(
1650
+ move1.modified({ amount: 1 })
1651
+ );
1652
+ if (move2) {
1653
+ quantumTransformation = this.kpuzzle.moveToTransformation(move2);
1654
+ }
1655
+ }
1656
+ if (!quantumTransformation) {
1657
+ console.log(e);
1658
+ throw e;
1659
+ }
1660
+ }
1661
+ const ax = this.axesInfo[unswizzled.family];
1662
+ const turnNormal = ax.axis;
1663
+ const angle = -this.ease(moveProgress.fraction) * moveProgress.direction * unswizzled.amount * TAU / ax.order;
1664
+ this.movingObj.rotateOnAxis(turnNormal, angle);
1665
+ const quantumTransformationData = quantumTransformation.transformationData;
1666
+ if (this.lastMoveTransformationData !== quantumTransformationData) {
1667
+ for (const orbit in this.stickers) {
1668
+ const pieces = this.stickers[orbit];
1669
+ const orin = pieces.length;
1670
+ const bmv = quantumTransformationData[orbit];
1671
+ for (let ori = 0; ori < orin; ori++) {
1672
+ const pieces2 = pieces[ori];
1673
+ for (let i = 0; i < pieces2.length; i++) {
1674
+ const p2 = pieces2[i];
1675
+ const ni = bmv.permutation[i];
1676
+ let tv = 0;
1677
+ if (ni !== i || bmv.orientationDelta[i] !== 0) {
1678
+ tv = 1;
1679
+ }
1680
+ if (tv !== p2.twistVal) {
1681
+ if (tv) {
1682
+ for (let j = p2.stickerStart; j < p2.stickerEnd; j++) {
1683
+ ind[j] |= 1;
1684
+ }
1685
+ for (let j = p2.hintStart; j < p2.hintEnd; j++) {
1686
+ ind[j] |= 1;
1687
+ }
1688
+ for (let j = p2.foundationStart; j < p2.foundationEnd; j++) {
1689
+ ind[j] |= 1;
1690
+ }
1691
+ } else {
1692
+ for (let j = p2.stickerStart; j < p2.stickerEnd; j++) {
1693
+ ind[j] &= ~1;
1694
+ }
1695
+ for (let j = p2.hintStart; j < p2.hintEnd; j++) {
1696
+ ind[j] &= ~1;
1697
+ }
1698
+ for (let j = p2.foundationStart; j < p2.foundationEnd; j++) {
1699
+ ind[j] &= ~1;
1700
+ }
1701
+ }
1702
+ p2.twistVal = tv;
1703
+ vismods++;
1704
+ }
1705
+ }
1706
+ }
1707
+ }
1708
+ this.lastMoveTransformationData = quantumTransformationData;
1709
+ }
1710
+ }
1711
+ if (this.#pendingStickeringUpdate || vismods) {
1712
+ this.filler.makeGroups(this.fixedGeo);
1713
+ }
1714
+ if (this.#pendingStickeringUpdate || colormods) {
1715
+ if (this.textured) {
1716
+ this.fixedGeo.getAttribute("uv").addUpdateRange(
1717
+ 0,
1718
+ 6 * this.foundationBound
1719
+ );
1720
+ this.fixedGeo.getAttribute("uv").needsUpdate = true;
1721
+ }
1722
+ if (this.#pendingStickeringUpdate || !this.textured) {
1723
+ this.fixedGeo.getAttribute("color").addUpdateRange(
1724
+ 0,
1725
+ 9 * this.foundationBound
1726
+ );
1727
+ this.fixedGeo.getAttribute("color").needsUpdate = true;
1728
+ }
1729
+ }
1730
+ this.scheduleRenderCallback();
1731
+ this.#pendingStickeringUpdate = false;
1732
+ }
1733
+ ease(fraction) {
1734
+ return smootherStep(fraction);
1735
+ }
1736
+ showHintFacelets(v) {
1737
+ this.showHintStickers = v;
1738
+ }
1739
+ updateMaterialArrays() {
1740
+ for (let i = 0; i < 8; i++) {
1741
+ this.materialArray1[i] = invisMaterial;
1742
+ this.materialArray2[i] = invisMaterial;
1743
+ }
1744
+ this.materialArray1[0] = this.stickerMaterial;
1745
+ this.materialArray2[1] = this.stickerMaterial;
1746
+ if (this.showHintStickers) {
1747
+ this.materialArray1[2] = this.hintMaterial;
1748
+ this.materialArray2[3] = this.hintMaterial;
1749
+ } else {
1750
+ this.materialArray1[2] = invisMaterial;
1751
+ this.materialArray2[3] = invisMaterial;
1752
+ }
1753
+ if (this.showFoundations) {
1754
+ this.materialArray1[6] = foundationMaterial;
1755
+ this.materialArray2[7] = foundationMaterial;
1756
+ } else {
1757
+ this.materialArray1[6] = invisMaterial;
1758
+ this.materialArray2[7] = invisMaterial;
1759
+ }
1760
+ }
1761
+ showFoundation(v) {
1762
+ this.showFoundations = v;
1763
+ }
1764
+ setHintStickerOpacity(v) {
1765
+ if (this.hintMaterialDisposable) {
1766
+ this.hintMaterial.dispose();
1767
+ this.hintMaterialDisposable = false;
1768
+ }
1769
+ if (v === 0) {
1770
+ this.hintMaterial = invisMaterial;
1771
+ } else if (v === 1) {
1772
+ this.hintMaterial = this.stickerMaterial;
1773
+ } else {
1774
+ this.hintMaterial = new MeshBasicMaterial2({
1775
+ vertexColors: true,
1776
+ transparent: true,
1777
+ opacity: v
1778
+ });
1779
+ this.hintMaterialDisposable = true;
1780
+ }
1781
+ }
1782
+ experimentalUpdateOptions(options) {
1783
+ if (options.hintFacelets !== void 0) {
1784
+ this.showHintFacelets(options.hintFacelets !== "none");
1785
+ }
1786
+ if (options.showFoundation !== void 0) {
1787
+ this.showFoundation(options.showFoundation);
1788
+ }
1789
+ if (options.hintStickerOpacity !== void 0) {
1790
+ this.setHintStickerOpacity(options.hintStickerOpacity);
1791
+ }
1792
+ this.#pendingStickeringUpdate = true;
1793
+ if (this.lastPos) {
1794
+ this.onPositionChange(this.lastPos);
1795
+ }
1796
+ if (typeof options.faceletScale !== "undefined" && options.faceletScale !== this.faceletScale) {
1797
+ console.warn(
1798
+ "Dynamic facelet scale is not yet supported for PG3D. For now, re-create the TwistyPlayer to change the facelet scale."
1799
+ );
1800
+ }
1801
+ this.updateMaterialArrays();
1802
+ this.scheduleRenderCallback();
1803
+ }
1804
+ adduvs() {
1805
+ const filler = this.filler;
1806
+ if (filler.uvs) {
1807
+ return;
1808
+ }
1809
+ this.filler.uvs = new Float32Array(12 * filler.sz);
1810
+ for (const orbit in this.stickers) {
1811
+ const pieces = this.stickers[orbit];
1812
+ const orin = pieces.length;
1813
+ for (let ori = 0; ori < orin; ori++) {
1814
+ const pieces2 = pieces[ori];
1815
+ for (const piece2 of pieces2) {
1816
+ piece2.addUVs(this.filler);
1817
+ }
1818
+ }
1819
+ }
1820
+ filler.uvs.copyWithin(6 * filler.sz, 0, 6 * filler.sz);
1821
+ const sa1 = filler.uvs.subarray(0, 6 * filler.sz);
1822
+ this.fixedGeo.setAttribute("uv", new BufferAttribute2(sa1, 2, true));
1823
+ }
1824
+ experimentalUpdateTexture(enabled, stickerTexture, hintTexture) {
1825
+ if (!stickerTexture) {
1826
+ enabled = false;
1827
+ }
1828
+ if (enabled && !this.filler.uvs) {
1829
+ this.adduvs();
1830
+ }
1831
+ this.textured = enabled;
1832
+ if (this.stickerMaterialDisposable) {
1833
+ this.stickerMaterial.dispose();
1834
+ this.stickerMaterialDisposable = false;
1835
+ }
1836
+ if (enabled) {
1837
+ this.stickerMaterial = new MeshBasicMaterial2({
1838
+ map: stickerTexture,
1839
+ side: FrontSide2,
1840
+ transparent: false
1841
+ });
1842
+ this.stickerMaterialDisposable = true;
1843
+ } else {
1844
+ this.stickerMaterial = basicStickerMaterial;
1845
+ }
1846
+ if (this.hintMaterialDisposable) {
1847
+ this.hintMaterial.dispose();
1848
+ this.hintMaterialDisposable = false;
1849
+ }
1850
+ if (enabled) {
1851
+ this.hintMaterial = new MeshBasicMaterial2({
1852
+ map: hintTexture,
1853
+ side: FrontSide2,
1854
+ transparent: true
1855
+ });
1856
+ this.hintMaterialDisposable = true;
1857
+ } else {
1858
+ this.hintMaterial = basicStickerMaterial;
1859
+ }
1860
+ if (enabled) {
1861
+ this.showHintFacelets(hintTexture !== null);
1862
+ }
1863
+ this.updateMaterialArrays();
1864
+ this.#pendingStickeringUpdate = true;
1865
+ if (this.lastPos) {
1866
+ this.onPositionChange(this.lastPos);
1867
+ }
1868
+ this.scheduleRenderCallback();
1869
+ }
1870
+ };
1871
+
1872
+ // src/cubing/twisty/views/3D/puzzles/Square1_3D.ts
1873
+ import { DoubleSide as DoubleSide3 } from "three/src/constants.js";
1874
+ import { BufferAttribute as BufferAttribute3 } from "three/src/core/BufferAttribute.js";
1875
+ import { BufferGeometry as BufferGeometry3 } from "three/src/core/BufferGeometry.js";
1876
+ import { Object3D as Object3D3 } from "three/src/core/Object3D.js";
1877
+ import { MeshBasicMaterial as MeshBasicMaterial3 } from "three/src/materials/MeshBasicMaterial.js";
1878
+ import { Color as Color3 } from "three/src/math/Color.js";
1879
+ import { Quaternion as Quaternion2 } from "three/src/math/Quaternion.js";
1880
+ import { Vector3 as Vector33 } from "three/src/math/Vector3.js";
1881
+ import { Group as Group3 } from "three/src/objects/Group.js";
1882
+ import { Mesh as Mesh3 } from "three/src/objects/Mesh.js";
1883
+ var DEGREE = TAU / 360;
1884
+ var SLOT_ANGLE_DEGREES = 30;
1885
+ var WEDGES_PER_LAYER = 12;
1886
+ var CUBE_HALF_EDGE = 1;
1887
+ var EQUATOR_HALF_HEIGHT = 0.25;
1888
+ var PUZZLE_SCALE = 0.5;
1889
+ var DEFAULT_FACELET_SCALE = 0.85;
1890
+ var STICKER_ELEVATION = 4e-3;
1891
+ var COLOR_UP = 16776960;
1892
+ var COLOR_DOWN = 16777215;
1893
+ var RING_COLORS = [2254591, 16750848, 65280, 16711680];
1894
+ var FRAME_OFFSET_DEGREES = 180;
1895
+ var BODY_COLOR = 1118481;
1896
+ var MIRROR = -1;
1897
+ var Y_AXIS = new Vector33(0, 1, 0);
1898
+ var SLICE_AXIS = new Vector33(
1899
+ MIRROR * Math.sin(15 * DEGREE),
1900
+ 0,
1901
+ Math.cos(15 * DEGREE)
1902
+ ).normalize();
1903
+ var SLICE_QUATERNION = new Quaternion2().setFromAxisAngle(SLICE_AXIS, TAU / 2);
1904
+ var HALF_TURN_Y = new Quaternion2().setFromAxisAngle(Y_AXIS, TAU / 2);
1905
+ function slotAzimuthDegrees(slot) {
1906
+ return FRAME_OFFSET_DEGREES + (slot < WEDGES_PER_LAYER ? SLOT_ANGLE_DEGREES * slot + 120 : 90 - SLOT_ANGLE_DEGREES * (slot - WEDGES_PER_LAYER));
1907
+ }
1908
+ function slotQuaternion(slot) {
1909
+ const quaternion = new Quaternion2().setFromAxisAngle(
1910
+ Y_AXIS,
1911
+ MIRROR * slotAzimuthDegrees(slot) * DEGREE
1912
+ );
1913
+ if (slot >= WEDGES_PER_LAYER) {
1914
+ quaternion.multiply(
1915
+ new Quaternion2().setFromAxisAngle(new Vector33(0, 0, 1), TAU / 2)
1916
+ );
1917
+ }
1918
+ return quaternion;
1919
+ }
1920
+ var SLOT_QUATERNIONS = new Array(2 * WEDGES_PER_LAYER).fill(null).map((_, slot) => slotQuaternion(slot));
1921
+ function wedgeShape(homeSlot) {
1922
+ const phase = homeSlot < WEDGES_PER_LAYER ? homeSlot % 3 : (homeSlot - WEDGES_PER_LAYER + 2) % 3;
1923
+ return phase === 0 ? "cornerHigh" : phase === 1 ? "cornerLow" : "edge";
1924
+ }
1925
+ function outerFaceOffsetDegrees(shape) {
1926
+ switch (shape) {
1927
+ case "cornerHigh":
1928
+ return -30;
1929
+ case "cornerLow":
1930
+ return 30;
1931
+ case "edge":
1932
+ return 0;
1933
+ }
1934
+ }
1935
+ function squarePoint(phiDegrees) {
1936
+ return polarPoint(phiDegrees, Math.round(phiDegrees / 90) * 90);
1937
+ }
1938
+ function polarPoint(phiDegrees, faceCenterDegrees) {
1939
+ const radius = CUBE_HALF_EDGE / Math.cos((phiDegrees - faceCenterDegrees) * DEGREE);
1940
+ const phi = phiDegrees * DEGREE;
1941
+ return [MIRROR * radius * Math.sin(phi), radius * Math.cos(phi)];
1942
+ }
1943
+ function wedgeCrossSection(shape) {
1944
+ const faceCenterDegrees = outerFaceOffsetDegrees(shape);
1945
+ return [
1946
+ [0, 0],
1947
+ polarPoint(-SLOT_ANGLE_DEGREES / 2, faceCenterDegrees),
1948
+ polarPoint(SLOT_ANGLE_DEGREES / 2, faceCenterDegrees)
1949
+ ];
1950
+ }
1951
+ function cornerCrossSection() {
1952
+ return [
1953
+ [0, 0],
1954
+ polarPoint(-SLOT_ANGLE_DEGREES / 2, -30),
1955
+ polarPoint(SLOT_ANGLE_DEGREES / 2, -30),
1956
+ // the cube corner, shared by both halves
1957
+ polarPoint(SLOT_ANGLE_DEGREES + SLOT_ANGLE_DEGREES / 2, 60)
1958
+ ];
1959
+ }
1960
+ var CORNER_PAIRS = [];
1961
+ for (let slot = 0; slot < 2 * WEDGES_PER_LAYER; slot++) {
1962
+ if (wedgeShape(slot) === "cornerHigh") {
1963
+ CORNER_PAIRS.push([slot, nextSlotInLayer(slot)]);
1964
+ }
1965
+ }
1966
+ function nextSlotInLayer(slot) {
1967
+ return slot < WEDGES_PER_LAYER ? (slot + 1) % WEDGES_PER_LAYER : WEDGES_PER_LAYER + (slot - WEDGES_PER_LAYER + 1) % WEDGES_PER_LAYER;
1968
+ }
1969
+ function wedgeSideColor(homeSlot) {
1970
+ return ringColorAt(slotAzimuthDegrees(homeSlot));
1971
+ }
1972
+ function prismBodyPositions(spec) {
1973
+ const { polygon, yBottom, yTop } = spec;
1974
+ const out = [];
1975
+ const n = polygon.length;
1976
+ for (const y of [yTop, yBottom]) {
1977
+ for (let i = 1; i < n - 1; i++) {
1978
+ out.push(
1979
+ polygon[0][0],
1980
+ y,
1981
+ polygon[0][1],
1982
+ polygon[i][0],
1983
+ y,
1984
+ polygon[i][1],
1985
+ polygon[i + 1][0],
1986
+ y,
1987
+ polygon[i + 1][1]
1988
+ );
1989
+ }
1990
+ }
1991
+ for (let i = 0; i < n; i++) {
1992
+ const [x0, z0] = polygon[i];
1993
+ const [x1, z1] = polygon[(i + 1) % n];
1994
+ out.push(x0, yBottom, z0, x1, yBottom, z1, x1, yTop, z1);
1995
+ out.push(x0, yBottom, z0, x1, yTop, z1, x0, yTop, z0);
1996
+ }
1997
+ return new Float32Array(out);
1998
+ }
1999
+ function prismStickerSpecs(spec) {
2000
+ const { polygon, yBottom, yTop, topColor, bottomColor, sideColors } = spec;
2001
+ const specs = [];
2002
+ if (topColor !== null) {
2003
+ specs.push({
2004
+ corners: polygon.map(([x, z]) => new Vector33(x, yTop, z)),
2005
+ normal: new Vector33(0, 1, 0),
2006
+ color: topColor
2007
+ });
2008
+ }
2009
+ if (bottomColor !== null) {
2010
+ specs.push({
2011
+ corners: polygon.map(([x, z]) => new Vector33(x, yBottom, z)),
2012
+ normal: new Vector33(0, -1, 0),
2013
+ color: bottomColor
2014
+ });
2015
+ }
2016
+ let centroidX = 0;
2017
+ let centroidZ = 0;
2018
+ for (const [x, z] of polygon) {
2019
+ centroidX += x / polygon.length;
2020
+ centroidZ += z / polygon.length;
2021
+ }
2022
+ for (let i = 0; i < polygon.length; i++) {
2023
+ const color = sideColors[i];
2024
+ if (color === null || color === void 0) {
2025
+ continue;
2026
+ }
2027
+ const [x0, z0] = polygon[i];
2028
+ const [x1, z1] = polygon[(i + 1) % polygon.length];
2029
+ const normal2 = new Vector33(z1 - z0, 0, -(x1 - x0)).normalize();
2030
+ const outward = normal2.x * ((x0 + x1) / 2 - centroidX) + normal2.z * ((z0 + z1) / 2 - centroidZ);
2031
+ if (outward < 0) {
2032
+ normal2.negate();
2033
+ }
2034
+ specs.push({
2035
+ corners: [
2036
+ new Vector33(x0, yBottom, z0),
2037
+ new Vector33(x1, yBottom, z1),
2038
+ new Vector33(x1, yTop, z1),
2039
+ new Vector33(x0, yTop, z0)
2040
+ ],
2041
+ normal: normal2,
2042
+ color
2043
+ });
2044
+ }
2045
+ return specs;
2046
+ }
2047
+ function stickerPositions(spec, faceletScale) {
2048
+ const center = new Vector33();
2049
+ for (const corner of spec.corners) {
2050
+ center.addScaledVector(corner, 1 / spec.corners.length);
2051
+ }
2052
+ const placed = spec.corners.map(
2053
+ (corner) => center.clone().addScaledVector(corner.clone().sub(center), faceletScale).addScaledVector(spec.normal, STICKER_ELEVATION)
2054
+ );
2055
+ const out = [];
2056
+ for (let i = 1; i < placed.length - 1; i++) {
2057
+ out.push(
2058
+ placed[0].x,
2059
+ placed[0].y,
2060
+ placed[0].z,
2061
+ placed[i].x,
2062
+ placed[i].y,
2063
+ placed[i].z,
2064
+ placed[i + 1].x,
2065
+ placed[i + 1].y,
2066
+ placed[i + 1].z
2067
+ );
2068
+ }
2069
+ return new Float32Array(out);
2070
+ }
2071
+ var bodyMaterial = new MeshBasicMaterial3({
2072
+ color: new Color3(BODY_COLOR).convertLinearToSRGB(),
2073
+ side: DoubleSide3
2074
+ });
2075
+ var stickerMaterialCache = /* @__PURE__ */ new Map();
2076
+ function stickerMaterial(color) {
2077
+ let material = stickerMaterialCache.get(color);
2078
+ if (!material) {
2079
+ material = new MeshBasicMaterial3({
2080
+ color: new Color3(color).convertLinearToSRGB(),
2081
+ side: DoubleSide3
2082
+ });
2083
+ stickerMaterialCache.set(color, material);
2084
+ }
2085
+ return material;
2086
+ }
2087
+ var Square1Piece = class extends Group3 {
2088
+ body;
2089
+ #stickerSpecs;
2090
+ #stickerMeshes = [];
2091
+ constructor(spec, faceletScale) {
2092
+ super();
2093
+ const bodyGeometry = new BufferGeometry3();
2094
+ bodyGeometry.setAttribute(
2095
+ "position",
2096
+ new BufferAttribute3(prismBodyPositions(spec), 3)
2097
+ );
2098
+ this.body = new Mesh3(bodyGeometry, bodyMaterial);
2099
+ this.add(this.body);
2100
+ this.#stickerSpecs = prismStickerSpecs(spec);
2101
+ for (const stickerSpec of this.#stickerSpecs) {
2102
+ const geometry = new BufferGeometry3();
2103
+ geometry.setAttribute(
2104
+ "position",
2105
+ new BufferAttribute3(stickerPositions(stickerSpec, faceletScale), 3)
2106
+ );
2107
+ const mesh = new Mesh3(geometry, stickerMaterial(stickerSpec.color));
2108
+ this.#stickerMeshes.push(mesh);
2109
+ this.add(mesh);
2110
+ }
2111
+ }
2112
+ setFaceletScale(faceletScale) {
2113
+ for (let i = 0; i < this.#stickerMeshes.length; i++) {
2114
+ const geometry = this.#stickerMeshes[i].geometry;
2115
+ geometry.setAttribute(
2116
+ "position",
2117
+ new BufferAttribute3(
2118
+ stickerPositions(this.#stickerSpecs[i], faceletScale),
2119
+ 3
2120
+ )
2121
+ );
2122
+ }
2123
+ }
2124
+ setFoundationVisible(visible) {
2125
+ this.body.visible = visible;
2126
+ }
2127
+ };
2128
+ function wedgePrismSpec(homeSlot) {
2129
+ const shape = wedgeShape(homeSlot);
2130
+ return {
2131
+ polygon: wedgeCrossSection(shape),
2132
+ yBottom: EQUATOR_HALF_HEIGHT,
2133
+ yTop: CUBE_HALF_EDGE,
2134
+ topColor: homeSlot < WEDGES_PER_LAYER ? COLOR_UP : COLOR_DOWN,
2135
+ bottomColor: null,
2136
+ sideColors: [null, wedgeSideColor(homeSlot), null]
2137
+ };
2138
+ }
2139
+ function cornerPrismSpec([high, low]) {
2140
+ return {
2141
+ polygon: cornerCrossSection(),
2142
+ yBottom: EQUATOR_HALF_HEIGHT,
2143
+ yTop: CUBE_HALF_EDGE,
2144
+ topColor: high < WEDGES_PER_LAYER ? COLOR_UP : COLOR_DOWN,
2145
+ bottomColor: null,
2146
+ sideColors: [null, wedgeSideColor(high), wedgeSideColor(low), null]
2147
+ };
2148
+ }
2149
+ function equatorPrismSpec(homePiece) {
2150
+ const startDegrees = FRAME_OFFSET_DEGREES + (homePiece === 0 ? 105 : 285);
2151
+ const boundaries = [startDegrees];
2152
+ for (let corner = Math.ceil((startDegrees - 45) / 90) * 90 + 45; corner < startDegrees + 180; corner += 90) {
2153
+ boundaries.push(corner);
2154
+ }
2155
+ boundaries.push(startDegrees + 180);
2156
+ return {
2157
+ polygon: boundaries.map((phiDegrees) => squarePoint(phiDegrees)),
2158
+ yBottom: -EQUATOR_HALF_HEIGHT,
2159
+ yTop: EQUATOR_HALF_HEIGHT,
2160
+ topColor: null,
2161
+ bottomColor: null,
2162
+ sideColors: [
2163
+ ...boundaries.slice(0, -1).map(
2164
+ (phiDegrees, i) => ringColorAt((phiDegrees + boundaries[i + 1]) / 2)
2165
+ ),
2166
+ null
2167
+ ]
2168
+ };
2169
+ }
2170
+ function ringColorAt(phiDegrees) {
2171
+ const faceIndex = Math.round(phiDegrees / 90);
2172
+ return RING_COLORS[(faceIndex % 4 + 4) % 4];
2173
+ }
2174
+ var Square1_3D = class extends Object3D3 {
2175
+ constructor(kpuzzle, scheduleRenderCallback, options = {}) {
2176
+ super();
2177
+ this.scheduleRenderCallback = scheduleRenderCallback;
2178
+ if (kpuzzle.name() !== "Square-1") {
2179
+ throw new Error(
2180
+ `Invalid puzzle for this Square1_3D implementation: ${kpuzzle.name()}`
2181
+ );
2182
+ }
2183
+ if (typeof options.faceletScale === "number") {
2184
+ this.#faceletScale = options.faceletScale;
2185
+ }
2186
+ if (typeof options.showFoundation === "boolean") {
2187
+ this.#showFoundation = options.showFoundation;
2188
+ }
2189
+ for (let piece = 0; piece < 2 * WEDGES_PER_LAYER; piece++) {
2190
+ const wedge = new Square1Piece(wedgePrismSpec(piece), this.#faceletScale);
2191
+ wedge.setFoundationVisible(this.#showFoundation);
2192
+ wedge.quaternion.copy(SLOT_QUATERNIONS[piece]);
2193
+ this.#wedgePieces.push(wedge);
2194
+ this.add(wedge);
2195
+ }
2196
+ for (const pair of CORNER_PAIRS) {
2197
+ const corner = new Square1Piece(
2198
+ cornerPrismSpec(pair),
2199
+ this.#faceletScale
2200
+ );
2201
+ corner.setFoundationVisible(this.#showFoundation);
2202
+ corner.visible = false;
2203
+ this.#cornerPieces.push(corner);
2204
+ this.add(corner);
2205
+ }
2206
+ for (let piece = 0; piece < 2; piece++) {
2207
+ const equator = new Square1Piece(
2208
+ equatorPrismSpec(piece),
2209
+ this.#faceletScale
2210
+ );
2211
+ equator.setFoundationVisible(this.#showFoundation);
2212
+ this.#equatorPieces.push(equator);
2213
+ this.add(equator);
2214
+ }
2215
+ this.scale.set(PUZZLE_SCALE, PUZZLE_SCALE, PUZZLE_SCALE);
2216
+ }
2217
+ scheduleRenderCallback;
2218
+ #wedgePieces = [];
2219
+ #cornerPieces = [];
2220
+ #equatorPieces = [];
2221
+ #faceletScale = DEFAULT_FACELET_SCALE;
2222
+ #showFoundation = true;
2223
+ #slotOfPiece = new Int8Array(2 * WEDGES_PER_LAYER);
2224
+ #slotMoveMask = new Uint8Array(2 * WEDGES_PER_LAYER);
2225
+ #slotRotation = new Array(2 * WEDGES_PER_LAYER).fill(
2226
+ null
2227
+ );
2228
+ onPositionChange(position) {
2229
+ const wedges = position.pattern.patternData["WEDGES"];
2230
+ const equator = position.pattern.patternData["EQUATOR"];
2231
+ for (let slot = 0; slot < 2 * WEDGES_PER_LAYER; slot++) {
2232
+ this.#slotOfPiece[wedges.pieces[slot]] = slot;
2233
+ this.#slotMoveMask[slot] = 0;
2234
+ this.#slotRotation[slot] = null;
2235
+ }
2236
+ let equatorRotation = null;
2237
+ let moveBit = 1;
2238
+ for (const moveInProgress of position.movesInProgress) {
2239
+ const { family, amount } = moveInProgress.move;
2240
+ const turns = smootherStep(moveInProgress.fraction) * moveInProgress.direction * amount;
2241
+ let slotStart;
2242
+ let slotEnd;
2243
+ const quaternion = new Quaternion2();
2244
+ switch (family) {
2245
+ case "U_SQ_":
2246
+ quaternion.setFromAxisAngle(
2247
+ Y_AXIS,
2248
+ MIRROR * turns * SLOT_ANGLE_DEGREES * DEGREE
2249
+ );
2250
+ slotStart = 0;
2251
+ slotEnd = WEDGES_PER_LAYER;
2252
+ break;
2253
+ case "D_SQ_":
2254
+ quaternion.setFromAxisAngle(
2255
+ Y_AXIS,
2256
+ -MIRROR * turns * SLOT_ANGLE_DEGREES * DEGREE
2257
+ );
2258
+ slotStart = WEDGES_PER_LAYER;
2259
+ slotEnd = 2 * WEDGES_PER_LAYER;
2260
+ break;
2261
+ case "_SLASH_":
2262
+ quaternion.setFromAxisAngle(SLICE_AXIS, turns * TAU / 2);
2263
+ slotStart = WEDGES_PER_LAYER / 2;
2264
+ slotEnd = WEDGES_PER_LAYER + WEDGES_PER_LAYER / 2;
2265
+ equatorRotation = quaternion;
2266
+ break;
2267
+ default:
2268
+ continue;
2269
+ }
2270
+ for (let slot = slotStart; slot < slotEnd; slot++) {
2271
+ const existing = this.#slotRotation[slot];
2272
+ this.#slotRotation[slot] = existing ? existing.clone().premultiply(quaternion) : quaternion;
2273
+ this.#slotMoveMask[slot] |= moveBit;
2274
+ }
2275
+ moveBit = moveBit << 1 & 255;
2276
+ }
2277
+ for (let piece = 0; piece < 2 * WEDGES_PER_LAYER; piece++) {
2278
+ this.#placeWedge(this.#wedgePieces[piece], this.#slotOfPiece[piece]);
2279
+ }
2280
+ for (let i = 0; i < CORNER_PAIRS.length; i++) {
2281
+ const [high, low] = CORNER_PAIRS[i];
2282
+ const highSlot = this.#slotOfPiece[high];
2283
+ const lowSlot = this.#slotOfPiece[low];
2284
+ const joined = nextSlotInLayer(highSlot) === lowSlot && this.#slotMoveMask[highSlot] === this.#slotMoveMask[lowSlot];
2285
+ this.#cornerPieces[i].visible = joined;
2286
+ this.#wedgePieces[high].visible = !joined;
2287
+ this.#wedgePieces[low].visible = !joined;
2288
+ if (joined) {
2289
+ this.#placeWedge(this.#cornerPieces[i], highSlot);
2290
+ }
2291
+ }
2292
+ for (let slot = 0; slot < 2; slot++) {
2293
+ const piece = equator.pieces[slot];
2294
+ const quaternion = this.#equatorPieces[piece].quaternion;
2295
+ quaternion.identity();
2296
+ if (piece !== slot) {
2297
+ quaternion.multiply(HALF_TURN_Y);
2298
+ }
2299
+ if ((equator.orientation[slot] % 6 + 6) % 6 >= 3) {
2300
+ quaternion.premultiply(SLICE_QUATERNION);
2301
+ }
2302
+ if (slot === 1 && equatorRotation) {
2303
+ quaternion.premultiply(equatorRotation);
2304
+ }
2305
+ }
2306
+ }
2307
+ #placeWedge(piece, slot) {
2308
+ const quaternion = piece.quaternion.copy(SLOT_QUATERNIONS[slot]);
2309
+ const rotation = this.#slotRotation[slot];
2310
+ if (rotation) {
2311
+ quaternion.premultiply(rotation);
2312
+ }
2313
+ }
2314
+ setStickeringMask(_stickeringMask) {
2315
+ }
2316
+ experimentalUpdateOptions(options) {
2317
+ let changed = false;
2318
+ if (typeof options.showFoundation === "boolean") {
2319
+ if (options.showFoundation !== this.#showFoundation) {
2320
+ this.#showFoundation = options.showFoundation;
2321
+ for (const piece of this.#allPieces()) {
2322
+ piece.setFoundationVisible(this.#showFoundation);
2323
+ }
2324
+ changed = true;
2325
+ }
2326
+ }
2327
+ if (typeof options.faceletScale !== "undefined") {
2328
+ const faceletScale = options.faceletScale === "auto" ? DEFAULT_FACELET_SCALE : options.faceletScale;
2329
+ if (faceletScale !== this.#faceletScale) {
2330
+ this.#faceletScale = faceletScale;
2331
+ for (const piece of this.#allPieces()) {
2332
+ piece.setFaceletScale(faceletScale);
2333
+ }
2334
+ changed = true;
2335
+ }
2336
+ }
2337
+ if (changed) {
2338
+ this.scheduleRenderCallback?.();
2339
+ }
2340
+ }
2341
+ *#allPieces() {
2342
+ yield* this.#wedgePieces;
2343
+ yield* this.#cornerPieces;
2344
+ yield* this.#equatorPieces;
2345
+ }
2346
+ };
2347
+
2348
+ // src/cubing/twisty/heavy-code-imports/dynamic-entries/twisty-dynamic-3d.ts
2349
+ import { PerspectiveCamera } from "three/src/cameras/PerspectiveCamera.js";
2350
+ import { Raycaster } from "three/src/core/Raycaster.js";
2351
+ import { TextureLoader as TextureLoader2 } from "three/src/loaders/TextureLoader.js";
2352
+ import { Spherical } from "three/src/math/Spherical.js";
2353
+ import { Vector2 as Vector22 } from "three/src/math/Vector2.js";
2354
+ import { Vector3 as Vector34 } from "three/src/math/Vector3.js";
2355
+ import { WebGLRenderer } from "three/src/renderers/WebGLRenderer.js";
2356
+ import { Scene } from "three/src/scenes/Scene.js";
2357
+
2358
+ // src/cubing/twisty/views/3D/Twisty3DScene.ts
2359
+ var Twisty3DScene = class {
2360
+ renderTargets = /* @__PURE__ */ new Set();
2361
+ twisty3Ds = /* @__PURE__ */ new Set();
2362
+ threeJSScene = (async () => new (await bulk3DCode).ThreeScene())();
2363
+ addRenderTarget(renderTarget) {
2364
+ this.renderTargets.add(renderTarget);
2365
+ }
2366
+ scheduleRender() {
2367
+ for (const renderTarget of this.renderTargets) {
2368
+ renderTarget.scheduleRender();
2369
+ }
2370
+ }
2371
+ async addTwisty3DPuzzle(twisty3DPuzzle) {
2372
+ this.twisty3Ds.add(twisty3DPuzzle);
2373
+ (await this.threeJSScene).add(twisty3DPuzzle);
2374
+ }
2375
+ async removeTwisty3DPuzzle(twisty3DPuzzle) {
2376
+ this.twisty3Ds.delete(twisty3DPuzzle);
2377
+ (await this.threeJSScene).remove(twisty3DPuzzle);
2378
+ }
2379
+ async clearPuzzles() {
2380
+ for (const puz of this.twisty3Ds) {
2381
+ (await this.threeJSScene).remove(puz);
2382
+ }
2383
+ this.twisty3Ds.clear();
2384
+ }
2385
+ };
2386
+
2387
+ // src/cubing/twisty/heavy-code-imports/dynamic-entries/twisty-dynamic-3d.ts
2388
+ async function cube3DShim(renderCallback, options) {
2389
+ return new Cube3D(await cube3x3x3.kpuzzle(), renderCallback, options);
2390
+ }
2391
+ async function square1_3DShim(renderCallback, puzzleLoader, faceletScale) {
2392
+ return new Square1_3D(await puzzleLoader.kpuzzle(), renderCallback, {
2393
+ faceletScale
2394
+ });
2395
+ }
2396
+ async function pg3dShim(renderCallback, puzzleLoader, hintFacelets, faceletScale, darkIgnoredOrbits) {
2397
+ return new PG3D(
2398
+ renderCallback,
2399
+ await puzzleLoader.kpuzzle(),
2400
+ (await puzzleLoader.pg()).get3d({ darkIgnoredOrbits }),
2401
+ true,
2402
+ hintFacelets === "floating",
2403
+ void 0,
2404
+ faceletScale
2405
+ );
2406
+ }
2407
+ export {
2408
+ Cube3D,
2409
+ PG3D,
2410
+ Square1_3D,
2411
+ PerspectiveCamera as ThreePerspectiveCamera,
2412
+ Raycaster as ThreeRaycaster,
2413
+ Scene as ThreeScene,
2414
+ Spherical as ThreeSpherical,
2415
+ TextureLoader2 as ThreeTextureLoader,
2416
+ Vector22 as ThreeVector2,
2417
+ Vector34 as ThreeVector3,
2418
+ WebGLRenderer as ThreeWebGLRenderer,
2419
+ Twisty3DScene,
2420
+ cube3DShim,
2421
+ pg3dShim,
2422
+ square1_3DShim
2423
+ };
2424
+ //# sourceMappingURL=twisty-dynamic-3d-JO6OGKOF.js.map