cubing 0.63.2 → 0.63.3

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 (62) hide show
  1. package/dist/bin/chunks/{chunk-52ODPET6.js → chunk-OI3YIXMQ.js} +2 -2
  2. package/dist/bin/order.js +1 -1
  3. package/dist/bin/puzzle-geometry-bin.js +1 -1
  4. package/dist/bin/scramble.js +1 -1
  5. package/dist/lib/cubing/{PuzzleLoader-R-puDLmC.d.ts → PuzzleLoader-Bp8zngUn.d.ts} +10 -0
  6. package/dist/lib/cubing/alg/index.d.ts +2 -2
  7. package/dist/lib/cubing/bluetooth/index.d.ts +2 -2
  8. package/dist/lib/cubing/chunks/chunk-44CFF24P.js +239 -0
  9. package/dist/lib/cubing/chunks/chunk-44CFF24P.js.map +7 -0
  10. package/dist/lib/cubing/chunks/chunk-DQGYYYHZ.js +1180 -0
  11. package/dist/lib/cubing/chunks/chunk-DQGYYYHZ.js.map +7 -0
  12. package/dist/lib/cubing/chunks/chunk-FTE3QI5X.js +1074 -0
  13. package/dist/lib/cubing/chunks/chunk-FTE3QI5X.js.map +7 -0
  14. package/dist/lib/cubing/chunks/chunk-FZBKZ5ZB.js +265 -0
  15. package/dist/lib/cubing/chunks/chunk-FZBKZ5ZB.js.map +7 -0
  16. package/dist/lib/cubing/chunks/chunk-OUM32GEA.js +239 -0
  17. package/dist/lib/cubing/chunks/chunk-OUM32GEA.js.map +7 -0
  18. package/dist/lib/cubing/chunks/chunk-SGJ5WPE4.js +1074 -0
  19. package/dist/lib/cubing/chunks/chunk-SGJ5WPE4.js.map +7 -0
  20. package/dist/lib/cubing/chunks/chunk-TAVR35KU.js +265 -0
  21. package/dist/lib/cubing/chunks/chunk-TAVR35KU.js.map +7 -0
  22. package/dist/lib/cubing/chunks/chunk-VRTKWZPL.js +10084 -0
  23. package/dist/lib/cubing/chunks/chunk-VRTKWZPL.js.map +7 -0
  24. package/dist/lib/cubing/chunks/chunk-VSMFYTG6.js +10086 -0
  25. package/dist/lib/cubing/chunks/chunk-VSMFYTG6.js.map +7 -0
  26. package/dist/lib/cubing/chunks/inside-IHWQVDVU.js +564 -0
  27. package/dist/lib/cubing/chunks/inside-IHWQVDVU.js.map +7 -0
  28. package/dist/lib/cubing/chunks/inside-L2JI2BEY.js +564 -0
  29. package/dist/lib/cubing/chunks/inside-L2JI2BEY.js.map +7 -0
  30. package/dist/lib/cubing/chunks/search-dynamic-sgs-side-events-MXHP7O4R.js +1890 -0
  31. package/dist/lib/cubing/chunks/search-dynamic-sgs-side-events-MXHP7O4R.js.map +7 -0
  32. package/dist/lib/cubing/chunks/search-dynamic-sgs-side-events-XFECDWOF.js +1890 -0
  33. package/dist/lib/cubing/chunks/search-dynamic-sgs-side-events-XFECDWOF.js.map +7 -0
  34. package/dist/lib/cubing/chunks/search-dynamic-sgs-unofficial-CM33KT7L.js +1267 -0
  35. package/dist/lib/cubing/chunks/search-dynamic-sgs-unofficial-CM33KT7L.js.map +7 -0
  36. package/dist/lib/cubing/chunks/search-dynamic-sgs-unofficial-Q4LLHL2O.js +1267 -0
  37. package/dist/lib/cubing/chunks/search-dynamic-sgs-unofficial-Q4LLHL2O.js.map +7 -0
  38. package/dist/lib/cubing/chunks/search-dynamic-solve-4x4x4-COSEVJBV.js +2922 -0
  39. package/dist/lib/cubing/chunks/search-dynamic-solve-4x4x4-COSEVJBV.js.map +7 -0
  40. package/dist/lib/cubing/chunks/search-dynamic-solve-4x4x4-NANDMURR.js +2922 -0
  41. package/dist/lib/cubing/chunks/search-dynamic-solve-4x4x4-NANDMURR.js.map +7 -0
  42. package/dist/lib/cubing/chunks/twisty-dynamic-3d-5NZRNZ7C.js +1881 -0
  43. package/dist/lib/cubing/chunks/twisty-dynamic-3d-5NZRNZ7C.js.map +7 -0
  44. package/dist/lib/cubing/chunks/twisty-dynamic-3d-VGZIQ64W.js +1927 -0
  45. package/dist/lib/cubing/chunks/twisty-dynamic-3d-VGZIQ64W.js.map +7 -0
  46. package/dist/lib/cubing/chunks/twisty-dynamic-3d-XLUOPCLN.js +1881 -0
  47. package/dist/lib/cubing/chunks/twisty-dynamic-3d-XLUOPCLN.js.map +7 -0
  48. package/dist/lib/cubing/{events-IfSwQLYm.d.ts → events-CewDA1aS.d.ts} +1 -1
  49. package/dist/lib/cubing/{index-btIxbuNp.d.ts → index-DabjED-w.d.ts} +1 -1
  50. package/dist/lib/cubing/kpuzzle/index.d.ts +1 -1
  51. package/dist/lib/cubing/notation/index.d.ts +1 -1
  52. package/dist/lib/cubing/protocol/index.d.ts +1 -1
  53. package/dist/lib/cubing/puzzle-geometry/index.d.ts +2 -2
  54. package/dist/lib/cubing/puzzles/index.d.ts +1 -1
  55. package/dist/lib/cubing/scramble/index.d.ts +2 -2
  56. package/dist/lib/cubing/search/index.d.ts +3 -3
  57. package/dist/lib/cubing/stream/index.d.ts +3 -3
  58. package/dist/lib/cubing/twisty/index.d.ts +2 -2
  59. package/dist/lib/cubing/twisty/index.js +37 -4
  60. package/dist/lib/cubing/twisty/index.js.map +3 -3
  61. package/package.json +1 -1
  62. /package/dist/bin/chunks/{chunk-52ODPET6.js.map → chunk-OI3YIXMQ.js.map} +0 -0
@@ -0,0 +1,1180 @@
1
+ import {
2
+ from
3
+ } from "./chunk-FUHYAW74.js";
4
+
5
+ // src/cubing/twisty/debug.ts
6
+ var twistyDebugGlobals = {
7
+ shareAllNewRenderers: "auto",
8
+ showRenderStats: false
9
+ };
10
+ function setTwistyDebug(options) {
11
+ for (const [key, value] of Object.entries(options)) {
12
+ if (key in twistyDebugGlobals) {
13
+ twistyDebugGlobals[key] = value;
14
+ }
15
+ }
16
+ }
17
+
18
+ // src/cubing/twisty/model/PromiseFreshener.ts
19
+ var StaleDropper = class {
20
+ #latestAssignedIdx = 0;
21
+ #latestResolvedIdx = 0;
22
+ queue(p) {
23
+ return new Promise(async (resolve, reject) => {
24
+ try {
25
+ const idx = ++this.#latestAssignedIdx;
26
+ const result = await p;
27
+ if (idx > this.#latestResolvedIdx) {
28
+ this.#latestResolvedIdx = idx;
29
+ resolve(result);
30
+ }
31
+ } catch (e) {
32
+ reject(e);
33
+ }
34
+ });
35
+ }
36
+ };
37
+
38
+ // src/cubing/twisty/model/props/TwistyProp.ts
39
+ var globalSourceGeneration = 0;
40
+ var TwistyPropParent = class {
41
+ // Don't overwrite this. Overwrite `canReuseValue` instead.
42
+ canReuse(v1, v2) {
43
+ return v1 === v2 || this.canReuseValue(v1, v2);
44
+ }
45
+ // Overwrite with a cheap semantic comparison when possible.
46
+ // Note that this is not called if `v1 === v2` (in which case the value is automatically reused).
47
+ canReuseValue(_v1, _v2) {
48
+ return false;
49
+ }
50
+ debugGetChildren() {
51
+ return Array.from(this.#children.values());
52
+ }
53
+ // Propagation
54
+ #children = /* @__PURE__ */ new Set();
55
+ addChild(child) {
56
+ this.#children.add(child);
57
+ }
58
+ removeChild(child) {
59
+ this.#children.delete(child);
60
+ }
61
+ lastSourceGeneration = 0;
62
+ // Synchronously marks all descendants as stale. This doesn't actually
63
+ // literally mark as stale, but it updates the last source generation, which
64
+ // is used to tell if a cahced result is stale.
65
+ markStale(sourceEvent) {
66
+ if (sourceEvent.detail.generation !== globalSourceGeneration) {
67
+ throw new Error("A TwistyProp was marked stale too late!");
68
+ }
69
+ if (this.lastSourceGeneration === sourceEvent.detail.generation) {
70
+ return;
71
+ }
72
+ this.lastSourceGeneration = sourceEvent.detail.generation;
73
+ for (const child of this.#children) {
74
+ child.markStale(sourceEvent);
75
+ }
76
+ this.#scheduleRawDispatch();
77
+ }
78
+ #rawListeners = /* @__PURE__ */ new Set();
79
+ /** @deprecated */
80
+ addRawListener(listener, options) {
81
+ this.#rawListeners.add(listener);
82
+ if (options?.initial) {
83
+ listener();
84
+ }
85
+ }
86
+ /** @deprecated */
87
+ removeRawListener(listener) {
88
+ this.#rawListeners.delete(listener);
89
+ }
90
+ /** @deprecated */
91
+ #scheduleRawDispatch() {
92
+ if (!this.#rawDispatchPending) {
93
+ this.#rawDispatchPending = true;
94
+ setTimeout(() => this.#dispatchRawListeners(), 0);
95
+ }
96
+ }
97
+ #rawDispatchPending = false;
98
+ #dispatchRawListeners() {
99
+ if (!this.#rawDispatchPending) {
100
+ throw new Error("Invalid dispatch state!");
101
+ }
102
+ for (const listener of this.#rawListeners) {
103
+ listener();
104
+ }
105
+ this.#rawDispatchPending = false;
106
+ }
107
+ #freshListeners = /* @__PURE__ */ new Map();
108
+ // TODO: Pick a better name.
109
+ addFreshListener(listener) {
110
+ const staleDropper = new StaleDropper();
111
+ let lastResult = null;
112
+ const callback = async () => {
113
+ const result = await staleDropper.queue(this.get());
114
+ if (lastResult !== null && this.canReuse(lastResult, result)) {
115
+ return;
116
+ }
117
+ lastResult = result;
118
+ listener(result);
119
+ };
120
+ this.#freshListeners.set(listener, callback);
121
+ this.addRawListener(callback, { initial: true });
122
+ }
123
+ removeFreshListener(listener) {
124
+ this.removeRawListener(this.#freshListeners.get(listener));
125
+ this.#freshListeners.delete(listener);
126
+ }
127
+ };
128
+ var TwistyPropSource = class extends TwistyPropParent {
129
+ #value;
130
+ constructor(initialValue) {
131
+ super();
132
+ this.#value = from(() => this.getDefaultValue());
133
+ if (initialValue) {
134
+ this.#value = this.deriveFromPromiseOrValue(initialValue, this.#value);
135
+ }
136
+ }
137
+ set(input) {
138
+ this.#value = this.deriveFromPromiseOrValue(input, this.#value);
139
+ const sourceEventDetail = {
140
+ sourceProp: this,
141
+ value: this.#value,
142
+ generation: ++globalSourceGeneration
143
+ };
144
+ this.markStale(
145
+ new CustomEvent("stale", {
146
+ detail: sourceEventDetail
147
+ })
148
+ );
149
+ }
150
+ async get() {
151
+ return this.#value;
152
+ }
153
+ async deriveFromPromiseOrValue(input, oldValuePromise) {
154
+ return this.derive(await input, oldValuePromise);
155
+ }
156
+ };
157
+ var SimpleTwistyPropSource = class extends TwistyPropSource {
158
+ derive(input) {
159
+ return input;
160
+ }
161
+ };
162
+ var NO_VALUE = Symbol("no value");
163
+ var TwistyPropDerived = class extends TwistyPropParent {
164
+ constructor(parents, userVisibleErrorTracker) {
165
+ super();
166
+ this.userVisibleErrorTracker = userVisibleErrorTracker;
167
+ this.#parents = parents;
168
+ for (const parent of Object.values(parents)) {
169
+ parent.addChild(this);
170
+ }
171
+ }
172
+ // cachedInputs:
173
+ #parents;
174
+ #cachedLastSuccessfulCalculation = null;
175
+ #cachedLatestGenerationCalculation = null;
176
+ async get() {
177
+ const generation = this.lastSourceGeneration;
178
+ if (this.#cachedLatestGenerationCalculation?.generation === generation) {
179
+ return this.#cachedLatestGenerationCalculation.output;
180
+ }
181
+ const latestGenerationCalculation = {
182
+ generation,
183
+ output: this.#cacheDerive(
184
+ this.#getParents(),
185
+ generation,
186
+ this.#cachedLastSuccessfulCalculation
187
+ )
188
+ };
189
+ this.#cachedLatestGenerationCalculation = latestGenerationCalculation;
190
+ this.userVisibleErrorTracker?.reset();
191
+ return latestGenerationCalculation.output;
192
+ }
193
+ async #getParents() {
194
+ const inputValuePromises = {};
195
+ for (const [key, parent] of Object.entries(this.#parents)) {
196
+ inputValuePromises[key] = parent.get();
197
+ }
198
+ const inputs = {};
199
+ for (const key in this.#parents) {
200
+ inputs[key] = await inputValuePromises[key];
201
+ }
202
+ return inputs;
203
+ }
204
+ async #cacheDerive(inputsPromise, generation, cachedLatestGenerationCalculation = null) {
205
+ const inputs = await inputsPromise;
206
+ const cache = (output) => {
207
+ this.#cachedLastSuccessfulCalculation = {
208
+ inputs,
209
+ output: Promise.resolve(output),
210
+ generation
211
+ };
212
+ return output;
213
+ };
214
+ if (!cachedLatestGenerationCalculation) {
215
+ return cache(await this.derive(inputs));
216
+ }
217
+ const cachedInputs = cachedLatestGenerationCalculation.inputs;
218
+ for (const key in this.#parents) {
219
+ const parent = this.#parents[key];
220
+ if (!parent.canReuse(inputs[key], cachedInputs[key])) {
221
+ return cache(await this.derive(inputs));
222
+ }
223
+ }
224
+ return cachedLatestGenerationCalculation.output;
225
+ }
226
+ };
227
+ var FreshListenerManager = class {
228
+ #disconnectionFunctions = [];
229
+ addListener(prop, listener) {
230
+ let disconnected = false;
231
+ const wrappedListener = (value) => {
232
+ if (disconnected) {
233
+ return;
234
+ }
235
+ listener(value);
236
+ };
237
+ prop.addFreshListener(wrappedListener);
238
+ this.#disconnectionFunctions.push(() => {
239
+ prop.removeFreshListener(wrappedListener);
240
+ disconnected = true;
241
+ });
242
+ }
243
+ // TODO: Figure out the signature to let us do overloads
244
+ /** @deprecated */
245
+ addMultiListener3(props, listener) {
246
+ this.addMultiListener(props, listener);
247
+ }
248
+ addMultiListener(props, listener) {
249
+ let disconnected = false;
250
+ let initialIgnoresLeft = props.length - 1;
251
+ const wrappedListener = async (_) => {
252
+ if (initialIgnoresLeft > 0) {
253
+ initialIgnoresLeft--;
254
+ return;
255
+ }
256
+ if (disconnected) {
257
+ return;
258
+ }
259
+ const promises = props.map(
260
+ (prop) => prop.get()
261
+ );
262
+ const values = await Promise.all(promises);
263
+ listener(values);
264
+ };
265
+ for (const prop of props) {
266
+ prop.addFreshListener(wrappedListener);
267
+ }
268
+ this.#disconnectionFunctions.push(() => {
269
+ for (const prop of props) {
270
+ prop.removeFreshListener(wrappedListener);
271
+ }
272
+ disconnected = true;
273
+ });
274
+ }
275
+ disconnect() {
276
+ for (const disconnectionFunction of this.#disconnectionFunctions) {
277
+ disconnectionFunction();
278
+ }
279
+ }
280
+ };
281
+
282
+ // src/cubing/twisty/views/node-custom-element-shims.ts
283
+ var HTMLElementStub = class {
284
+ };
285
+ var HTMLElementShim;
286
+ if (globalThis.HTMLElement) {
287
+ HTMLElementShim = globalThis.HTMLElement;
288
+ } else {
289
+ HTMLElementShim = HTMLElementStub;
290
+ }
291
+ var CustomElementsStub = class {
292
+ define() {
293
+ }
294
+ };
295
+ var customElementsShim;
296
+ if (globalThis.customElements) {
297
+ customElementsShim = globalThis.customElements;
298
+ } else {
299
+ customElementsShim = new CustomElementsStub();
300
+ }
301
+ var cssStyleSheetShim;
302
+ var CSSStyleSheetStub = class {
303
+ replaceSync() {
304
+ }
305
+ };
306
+ if (globalThis.CSSStyleSheet) {
307
+ cssStyleSheetShim = globalThis.CSSStyleSheet;
308
+ } else {
309
+ cssStyleSheetShim = CSSStyleSheetStub;
310
+ }
311
+
312
+ // src/cubing/twisty/views/ManagedCustomElement.ts
313
+ var ManagedCustomElement = class extends HTMLElementShim {
314
+ shadow;
315
+ // TODO: hide this
316
+ contentWrapper;
317
+ // TODO: can we get rid of this wrapper?
318
+ constructor(options) {
319
+ super();
320
+ this.shadow = this.attachShadow({ mode: options?.mode ?? "closed" });
321
+ this.contentWrapper = document.createElement("div");
322
+ this.contentWrapper.classList.add("wrapper");
323
+ this.shadow.appendChild(this.contentWrapper);
324
+ }
325
+ // Add the source, if not already added.
326
+ // Returns the existing if it's already on the element.
327
+ addCSS(cssSource) {
328
+ this.shadow.adoptedStyleSheets.push(cssSource);
329
+ }
330
+ removeCSS(cssSource) {
331
+ const cssIndex = this.shadow.adoptedStyleSheets.indexOf(cssSource);
332
+ if (typeof cssIndex !== "undefined") {
333
+ this.shadow.adoptedStyleSheets.splice(cssIndex, cssIndex + 1);
334
+ }
335
+ }
336
+ addElement(element) {
337
+ return this.contentWrapper.appendChild(element);
338
+ }
339
+ prependElement(element) {
340
+ this.contentWrapper.prepend(element);
341
+ }
342
+ removeElement(element) {
343
+ return this.contentWrapper.removeChild(element);
344
+ }
345
+ };
346
+ customElementsShim.define(
347
+ "twisty-managed-custom-element",
348
+ ManagedCustomElement
349
+ );
350
+
351
+ // src/cubing/twisty/controllers/RenderScheduler.ts
352
+ var RenderScheduler = class {
353
+ constructor(callback) {
354
+ this.callback = callback;
355
+ }
356
+ animFrameID = null;
357
+ animFrame = this.animFrameWrapper.bind(this);
358
+ requestIsPending() {
359
+ return !!this.animFrameID;
360
+ }
361
+ requestAnimFrame() {
362
+ if (!this.animFrameID) {
363
+ this.animFrameID = requestAnimationFrame(this.animFrame);
364
+ }
365
+ }
366
+ cancelAnimFrame() {
367
+ if (this.animFrameID) {
368
+ cancelAnimationFrame(this.animFrameID);
369
+ this.animFrameID = 0;
370
+ }
371
+ }
372
+ animFrameWrapper(timestamp) {
373
+ this.animFrameID = 0;
374
+ this.callback(timestamp);
375
+ }
376
+ };
377
+
378
+ // src/cubing/twisty/model/props/puzzle/display/HintFaceletProp.ts
379
+ var hintFaceletStyles = {
380
+ floating: true,
381
+ // default
382
+ none: true
383
+ };
384
+ var HintFaceletProp = class extends SimpleTwistyPropSource {
385
+ getDefaultValue() {
386
+ return "auto";
387
+ }
388
+ };
389
+
390
+ // src/cubing/twisty/views/3D/TAU.ts
391
+ var TAU = Math.PI * 2;
392
+ var DEGREES_PER_RADIAN = 360 / TAU;
393
+
394
+ // src/cubing/vendor/mit/three/examples/jsm/libs/stats.modified.module.ts
395
+ var performance = globalThis.performance;
396
+ var Stats = class {
397
+ mode = 0;
398
+ dom = document.createElement("div");
399
+ constructor() {
400
+ this.dom.style.cssText = "position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";
401
+ this.dom.addEventListener(
402
+ "click",
403
+ (event) => {
404
+ event.preventDefault();
405
+ this.showPanel(++this.mode % this.dom.children.length);
406
+ },
407
+ false
408
+ );
409
+ this.showPanel(0);
410
+ }
411
+ addPanel(panel) {
412
+ this.dom.appendChild(panel.dom);
413
+ return panel;
414
+ }
415
+ showPanel(id) {
416
+ for (let i = 0; i < this.dom.children.length; i++) {
417
+ this.dom.children[i].style.display = i === id ? "block" : "none";
418
+ }
419
+ this.mode = id;
420
+ }
421
+ beginTime = (performance || Date).now();
422
+ prevTime = this.beginTime;
423
+ frames = 0;
424
+ fpsPanel = this.addPanel(new StatsPanel("FPS", "#0ff", "#002"));
425
+ msPanel = this.addPanel(new StatsPanel("MS", "#0f0", "#020"));
426
+ memPanel = performance?.memory ? this.addPanel(new StatsPanel("MB", "#f08", "#201")) : null;
427
+ REVISION = 16;
428
+ begin() {
429
+ this.beginTime = (performance || Date).now();
430
+ }
431
+ end() {
432
+ this.frames++;
433
+ const time = (performance || Date).now();
434
+ this.msPanel.update(time - this.beginTime, 200);
435
+ if (time >= this.prevTime + 1e3) {
436
+ this.fpsPanel.update(this.frames * 1e3 / (time - this.prevTime), 100);
437
+ this.prevTime = time;
438
+ this.frames = 0;
439
+ if (this.memPanel) {
440
+ const memory = performance.memory;
441
+ this.memPanel.update(
442
+ memory.usedJSHeapSize / 1048576,
443
+ memory.jsHeapSizeLimit / 1048576
444
+ );
445
+ }
446
+ }
447
+ return time;
448
+ }
449
+ update() {
450
+ this.beginTime = this.end();
451
+ }
452
+ };
453
+ var PR = Math.round(globalThis?.window?.devicePixelRatio ?? 1);
454
+ var WIDTH = 80 * PR;
455
+ var HEIGHT = 48 * PR;
456
+ var TEXT_X = 3 * PR;
457
+ var TEXT_Y = 2 * PR;
458
+ var GRAPH_X = 3 * PR;
459
+ var GRAPH_Y = 15 * PR;
460
+ var GRAPH_WIDTH = 74 * PR;
461
+ var GRAPH_HEIGHT = 30 * PR;
462
+ var StatsPanel = class {
463
+ constructor(name, fg, bg) {
464
+ this.name = name;
465
+ this.fg = fg;
466
+ this.bg = bg;
467
+ this.dom.width = WIDTH;
468
+ this.dom.height = HEIGHT;
469
+ this.dom.style.cssText = "width:80px;height:48px";
470
+ this.context.font = `bold ${9 * PR}px Helvetica,Arial,sans-serif`;
471
+ this.context.textBaseline = "top";
472
+ this.context.fillStyle = bg;
473
+ this.context.fillRect(0, 0, WIDTH, HEIGHT);
474
+ this.context.fillStyle = fg;
475
+ this.context.fillText(name, TEXT_X, TEXT_Y);
476
+ this.context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
477
+ this.context.fillStyle = bg;
478
+ this.context.globalAlpha = 0.9;
479
+ this.context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
480
+ }
481
+ min = Infinity;
482
+ max = 0;
483
+ dom = document.createElement("canvas");
484
+ context = this.dom.getContext("2d");
485
+ update(value, maxValue) {
486
+ this.min = Math.min(this.min, value);
487
+ this.max = Math.max(this.max, value);
488
+ this.context.fillStyle = this.bg;
489
+ this.context.globalAlpha = 1;
490
+ this.context.fillRect(0, 0, WIDTH, GRAPH_Y);
491
+ this.context.fillStyle = this.fg;
492
+ this.context.fillText(
493
+ `${Math.round(value)} ${this.name} (${Math.round(this.min)}-${Math.round(
494
+ this.max
495
+ )})`,
496
+ TEXT_X,
497
+ TEXT_Y
498
+ );
499
+ this.context.drawImage(
500
+ this.dom,
501
+ GRAPH_X + PR,
502
+ GRAPH_Y,
503
+ GRAPH_WIDTH - PR,
504
+ GRAPH_HEIGHT,
505
+ GRAPH_X,
506
+ GRAPH_Y,
507
+ GRAPH_WIDTH - PR,
508
+ GRAPH_HEIGHT
509
+ );
510
+ this.context.fillRect(
511
+ GRAPH_X + GRAPH_WIDTH - PR,
512
+ GRAPH_Y,
513
+ PR,
514
+ GRAPH_HEIGHT
515
+ );
516
+ this.context.fillStyle = this.bg;
517
+ this.context.globalAlpha = 0.9;
518
+ this.context.fillRect(
519
+ GRAPH_X + GRAPH_WIDTH - PR,
520
+ GRAPH_Y,
521
+ PR,
522
+ Math.round((1 - value / maxValue) * GRAPH_HEIGHT)
523
+ );
524
+ }
525
+ };
526
+
527
+ // src/cubing/twisty/heavy-code-imports/3d.ts
528
+ var cachedConstructorProxy = null;
529
+ async function bulk3DCode() {
530
+ return cachedConstructorProxy ??= import("./twisty-dynamic-3d-VGZIQ64W.js");
531
+ }
532
+
533
+ // src/cubing/twisty/views/canvas.ts
534
+ var globalPixelRatioOverride = null;
535
+ function pixelRatio() {
536
+ return globalPixelRatioOverride ?? (devicePixelRatio || 1);
537
+ }
538
+
539
+ // src/cubing/twisty/views/3D/DragTracker.ts
540
+ var MOVEMENT_EPSILON = 0.1;
541
+ var DragTracker = class extends EventTarget {
542
+ constructor(target) {
543
+ super();
544
+ this.target = target;
545
+ }
546
+ #dragInfoMap = /* @__PURE__ */ new Map();
547
+ // Idempotent
548
+ start() {
549
+ this.addTargetListener("pointerdown", this.onPointerDown.bind(this));
550
+ this.addTargetListener("contextmenu", (e) => {
551
+ e.preventDefault();
552
+ });
553
+ this.addTargetListener(
554
+ "touchmove",
555
+ (e) => e.preventDefault()
556
+ );
557
+ this.addTargetListener("dblclick", (e) => e.preventDefault());
558
+ }
559
+ // Idempotent
560
+ stop() {
561
+ for (const [eventType, listener] of this.#targetListeners.entries()) {
562
+ this.target.removeEventListener(
563
+ eventType,
564
+ listener
565
+ );
566
+ }
567
+ this.#targetListeners.clear();
568
+ this.#lazyListenersRegistered = false;
569
+ }
570
+ #targetListeners = /* @__PURE__ */ new Map();
571
+ addTargetListener(eventType, listener) {
572
+ if (!this.#targetListeners.has(eventType)) {
573
+ this.target.addEventListener(
574
+ eventType,
575
+ listener
576
+ // TODO
577
+ );
578
+ this.#targetListeners.set(eventType, listener);
579
+ }
580
+ }
581
+ // This allows us to avoid getting a callback every time the pointer moves over the canvas, until we have a down event.
582
+ // TODO: Ideally we'd also support unregistering when we're certain there are no more active touches. But this means we need to properly handle every way a pointer "click" can end, which is tricky across environments (due to e.g. mouse vs. touch vs. stylues, canvas/viewport/window/scroll boundaries, right-click and other ways of losing focus, etc.), so we conservatively leave the listeners on.
583
+ #lazyListenersRegistered = false;
584
+ #registerLazyListeners() {
585
+ if (this.#lazyListenersRegistered) {
586
+ return;
587
+ }
588
+ this.addTargetListener("pointermove", this.onPointerMove.bind(this));
589
+ this.addTargetListener("pointerup", this.onPointerUp.bind(this));
590
+ this.#lazyListenersRegistered = true;
591
+ }
592
+ #clear(e) {
593
+ this.#dragInfoMap.delete(e.pointerId);
594
+ }
595
+ // `null`: means: ignore this result (no movement, or not
596
+ #trackDrag(e) {
597
+ const existing = this.#dragInfoMap.get(e.pointerId);
598
+ if (!existing) {
599
+ return { movementInfo: null, hasMoved: false };
600
+ }
601
+ let movementInfo;
602
+ if ((e.movementX ?? 0) !== 0 || (e.movementY ?? 0) !== 0) {
603
+ movementInfo = {
604
+ attachedInfo: existing.attachedInfo,
605
+ movementX: e.movementX,
606
+ movementY: e.movementY,
607
+ elapsedMs: e.timeStamp - existing.lastTimeStamp
608
+ };
609
+ } else {
610
+ movementInfo = {
611
+ attachedInfo: existing.attachedInfo,
612
+ movementX: e.clientX - existing.lastClientX,
613
+ movementY: e.clientY - existing.lastClientY,
614
+ elapsedMs: e.timeStamp - existing.lastTimeStamp
615
+ };
616
+ }
617
+ existing.lastClientX = e.clientX;
618
+ existing.lastClientY = e.clientY;
619
+ existing.lastTimeStamp = e.timeStamp;
620
+ if (Math.abs(movementInfo.movementX) < MOVEMENT_EPSILON && Math.abs(movementInfo.movementY) < MOVEMENT_EPSILON) {
621
+ return { movementInfo: null, hasMoved: existing.hasMoved };
622
+ } else {
623
+ existing.hasMoved = true;
624
+ return { movementInfo, hasMoved: existing.hasMoved };
625
+ }
626
+ }
627
+ onPointerDown(e) {
628
+ this.#registerLazyListeners();
629
+ const newDragInfo = {
630
+ attachedInfo: {},
631
+ hasMoved: false,
632
+ lastClientX: e.clientX,
633
+ lastClientY: e.clientY,
634
+ lastTimeStamp: e.timeStamp
635
+ };
636
+ this.#dragInfoMap.set(e.pointerId, newDragInfo);
637
+ this.target.setPointerCapture(e.pointerId);
638
+ }
639
+ onPointerMove(e) {
640
+ const movementInfo = this.#trackDrag(e).movementInfo;
641
+ if (movementInfo) {
642
+ e.preventDefault();
643
+ this.dispatchEvent(
644
+ new CustomEvent("move", {
645
+ detail: movementInfo
646
+ })
647
+ );
648
+ }
649
+ }
650
+ onPointerUp(e) {
651
+ const trackDragResult = this.#trackDrag(e);
652
+ const existing = this.#dragInfoMap.get(e.pointerId);
653
+ this.#clear(e);
654
+ this.target.releasePointerCapture(e.pointerId);
655
+ let event;
656
+ if (trackDragResult.hasMoved) {
657
+ event = new CustomEvent("up", {
658
+ detail: { attachedInfo: existing.attachedInfo }
659
+ });
660
+ } else {
661
+ const { altKey, ctrlKey, metaKey, shiftKey } = e;
662
+ event = new CustomEvent("press", {
663
+ detail: {
664
+ normalizedX: e.offsetX / this.target.offsetWidth * 2 - 1,
665
+ normalizedY: 1 - e.offsetY / this.target.offsetHeight * 2,
666
+ rightClick: !!(e.button & 2),
667
+ keys: {
668
+ altKey,
669
+ ctrlOrMetaKey: ctrlKey || metaKey,
670
+ shiftKey
671
+ }
672
+ }
673
+ });
674
+ }
675
+ this.dispatchEvent(event);
676
+ }
677
+ };
678
+
679
+ // src/cubing/twisty/views/3D/RendererPool.ts
680
+ var renderers = [];
681
+ async function rawRenderPooled(width, height, scene, camera) {
682
+ if (renderers.length === 0) {
683
+ renderers.push(newRenderer());
684
+ }
685
+ const renderer = await renderers[0];
686
+ renderer.setSize(width, height);
687
+ renderer.render(scene, camera);
688
+ return renderer.domElement;
689
+ }
690
+ async function renderPooled(width, height, canvas, scene, camera) {
691
+ if (width === 0 || height === 0) {
692
+ return;
693
+ }
694
+ if (renderers.length === 0) {
695
+ renderers.push(newRenderer());
696
+ }
697
+ const rendererCanvas = await rawRenderPooled(width, height, scene, camera);
698
+ const context = canvas.getContext("2d");
699
+ context.clearRect(0, 0, canvas.width, canvas.height);
700
+ context.drawImage(rendererCanvas, 0, 0);
701
+ }
702
+ var linearSRGBColorSpace = "srgb-linear";
703
+ async function newRenderer() {
704
+ const rendererConstructor = (await bulk3DCode()).ThreeWebGLRenderer;
705
+ const renderer = new rendererConstructor({
706
+ antialias: true,
707
+ alpha: true
708
+ });
709
+ renderer.outputColorSpace = linearSRGBColorSpace;
710
+ renderer.setPixelRatio(pixelRatio());
711
+ return renderer;
712
+ }
713
+
714
+ // src/cubing/twisty/views/3D/Twisty3DVantage.css.ts
715
+ var twisty3DVantageCSS = new cssStyleSheetShim();
716
+ twisty3DVantageCSS.replaceSync(
717
+ `
718
+ :host {
719
+ width: 384px;
720
+ height: 256px;
721
+ display: grid;
722
+ }
723
+
724
+ .wrapper {
725
+ width: 100%;
726
+ height: 100%;
727
+ display: grid;
728
+ overflow: hidden;
729
+ place-content: center;
730
+ contain: strict;
731
+ }
732
+
733
+ .loading {
734
+ width: 4em;
735
+ height: 4em;
736
+ border-radius: 2.5em;
737
+ border: 0.5em solid rgba(0, 0, 0, 0);
738
+ border-top: 0.5em solid rgba(0, 0, 0, 0.7);
739
+ border-right: 0.5em solid rgba(0, 0, 0, 0.7);
740
+ animation: fade-in-delayed 4s, rotate 1s linear infinite;
741
+ }
742
+
743
+ @keyframes fade-in-delayed {
744
+ 0% { opacity: 0; }
745
+ 25% {opacity: 0; }
746
+ 100% { opacity: 1; }
747
+ }
748
+
749
+ @keyframes rotate {
750
+ from { transform: rotate(0deg); }
751
+ to { transform: rotate(360deg); }
752
+ }
753
+
754
+ /* TODO: This is due to stats hack. Replace with \`canvas\`. */
755
+ .wrapper > canvas {
756
+ max-width: 100%;
757
+ max-height: 100%;
758
+ animation: fade-in 0.25s ease-in;
759
+ }
760
+
761
+ @keyframes fade-in {
762
+ from { opacity: 0; }
763
+ to { opacity: 1; }
764
+ }
765
+
766
+ .wrapper.invisible {
767
+ opacity: 0;
768
+ }
769
+
770
+ .wrapper.drag-input-enabled > canvas {
771
+ cursor: grab;
772
+ }
773
+
774
+ .wrapper.drag-input-enabled > canvas:active {
775
+ cursor: grabbing;
776
+ }
777
+ `
778
+ );
779
+
780
+ // src/cubing/twisty/views/3D/TwistyOrbitControls.ts
781
+ var INERTIA_DEFAULT = true;
782
+ var INERTIA_DURATION_MS = 500;
783
+ var INERTIA_TIMEOUT_MS = 50;
784
+ var VERTICAL_MOVEMENT_BASE_SCALE = 0.75;
785
+ function momentumScale(progress) {
786
+ return (Math.exp(1 - progress) - (1 - progress)) / (1 - Math.E) + 1;
787
+ }
788
+ var Inertia = class {
789
+ constructor(startTimestamp, momentumX, momentumY, callback) {
790
+ this.startTimestamp = startTimestamp;
791
+ this.momentumX = momentumX;
792
+ this.momentumY = momentumY;
793
+ this.callback = callback;
794
+ this.scheduler.requestAnimFrame();
795
+ this.lastTimestamp = startTimestamp;
796
+ }
797
+ scheduler = new RenderScheduler(this.render.bind(this));
798
+ lastTimestamp;
799
+ render(now) {
800
+ const progressBefore = (this.lastTimestamp - this.startTimestamp) / INERTIA_DURATION_MS;
801
+ const progressAfter = Math.min(
802
+ 1,
803
+ (now - this.startTimestamp) / INERTIA_DURATION_MS
804
+ );
805
+ if (progressBefore === 0 && progressAfter > INERTIA_TIMEOUT_MS / INERTIA_DURATION_MS) {
806
+ return;
807
+ }
808
+ const delta = momentumScale(progressAfter) - momentumScale(progressBefore);
809
+ this.callback(this.momentumX * delta * 1e3, this.momentumY * delta * 1e3);
810
+ if (progressAfter < 1) {
811
+ this.scheduler.requestAnimFrame();
812
+ }
813
+ this.lastTimestamp = now;
814
+ }
815
+ };
816
+ var TwistyOrbitControls = class {
817
+ constructor(model, mirror, canvas, dragTracker) {
818
+ this.model = model;
819
+ this.mirror = mirror;
820
+ this.canvas = canvas;
821
+ this.dragTracker = dragTracker;
822
+ this.dragTracker.addEventListener(
823
+ "move",
824
+ this.onMove.bind(this)
825
+ // TODO: https://github.com/microsoft/TypeScript/issues/28357
826
+ );
827
+ this.dragTracker.addEventListener(
828
+ "up",
829
+ this.onUp.bind(this)
830
+ // TODO: https://github.com/microsoft/TypeScript/issues/28357
831
+ );
832
+ }
833
+ /** @deprecated */
834
+ experimentalInertia = INERTIA_DEFAULT;
835
+ onMovementBound = this.onMovement.bind(this);
836
+ experimentalHasBeenMoved = false;
837
+ // f is the fraction of the canvas traversed per ms.
838
+ temperMovement(f) {
839
+ return Math.sign(f) * Math.log(Math.abs(f * 10) + 1) / 6;
840
+ }
841
+ onMove(e) {
842
+ e.detail.attachedInfo ??= {};
843
+ const { temperedX, temperedY } = this.onMovement(
844
+ e.detail.movementX,
845
+ e.detail.movementY
846
+ );
847
+ const attachedInfo = e.detail.attachedInfo;
848
+ attachedInfo.lastTemperedX = temperedX * 10;
849
+ attachedInfo.lastTemperedY = temperedY * 10;
850
+ attachedInfo.timestamp = e.timeStamp;
851
+ }
852
+ onMovement(movementX, movementY) {
853
+ const scale = this.mirror ? -1 : 1;
854
+ const minDim = Math.min(this.canvas.offsetWidth, this.canvas.offsetHeight);
855
+ const temperedX = this.temperMovement(movementX / minDim);
856
+ const temperedY = this.temperMovement(
857
+ movementY / minDim * VERTICAL_MOVEMENT_BASE_SCALE
858
+ );
859
+ this.model.twistySceneModel.orbitCoordinatesRequest.set(
860
+ (async () => {
861
+ const prevCoords = await this.model.twistySceneModel.orbitCoordinates.get();
862
+ const newCoords = {
863
+ latitude: prevCoords.latitude + 2 * temperedY * DEGREES_PER_RADIAN * scale,
864
+ longitude: prevCoords.longitude - 2 * temperedX * DEGREES_PER_RADIAN
865
+ };
866
+ return newCoords;
867
+ })()
868
+ );
869
+ return { temperedX, temperedY };
870
+ }
871
+ onUp(e) {
872
+ e.preventDefault();
873
+ if ("lastTemperedX" in e.detail.attachedInfo && "lastTemperedY" in e.detail.attachedInfo && "timestamp" in e.detail.attachedInfo && e.timeStamp - e.detail.attachedInfo["timestamp"] < 60) {
874
+ new Inertia(
875
+ e.timeStamp,
876
+ // TODO
877
+ e.detail.attachedInfo.lastTemperedX,
878
+ e.detail.attachedInfo.lastTemperedY,
879
+ this.onMovementBound
880
+ );
881
+ }
882
+ }
883
+ };
884
+
885
+ // src/cubing/twisty/views/3D/Twisty3DVantage.ts
886
+ async function setCameraFromOrbitCoordinates(camera, orbitCoordinates, backView = false) {
887
+ const spherical = new (await bulk3DCode()).ThreeSpherical(
888
+ orbitCoordinates.distance,
889
+ (90 - (backView ? -1 : 1) * orbitCoordinates.latitude) / DEGREES_PER_RADIAN,
890
+ ((backView ? 180 : 0) + orbitCoordinates.longitude) / DEGREES_PER_RADIAN
891
+ );
892
+ spherical.makeSafe();
893
+ camera.position.setFromSpherical(spherical);
894
+ camera.lookAt(0, 0, 0);
895
+ }
896
+ var dedicatedRenderersSoFar = 0;
897
+ var DEFAULT_MAX_DEDICATED_RENDERERS = 2;
898
+ var sharingRenderers = false;
899
+ function shareRenderer() {
900
+ if (twistyDebugGlobals.shareAllNewRenderers !== "auto") {
901
+ if (!twistyDebugGlobals.shareAllNewRenderers) {
902
+ dedicatedRenderersSoFar++;
903
+ }
904
+ return twistyDebugGlobals.shareAllNewRenderers !== "never";
905
+ }
906
+ if (dedicatedRenderersSoFar < DEFAULT_MAX_DEDICATED_RENDERERS) {
907
+ dedicatedRenderersSoFar++;
908
+ return false;
909
+ } else {
910
+ sharingRenderers = true;
911
+ return true;
912
+ }
913
+ }
914
+ function haveStartedSharingRenderers() {
915
+ return sharingRenderers;
916
+ }
917
+ var Twisty3DVantage = class extends ManagedCustomElement {
918
+ constructor(model, scene, options) {
919
+ super();
920
+ this.model = model;
921
+ this.options = options;
922
+ this.scene = scene ?? null;
923
+ this.loadingElement = this.addElement(document.createElement("div"));
924
+ this.loadingElement.classList.add("loading");
925
+ if (twistyDebugGlobals.showRenderStats) {
926
+ this.stats = new Stats();
927
+ this.stats.dom.style.position = "absolute";
928
+ this.contentWrapper.appendChild(this.stats.dom);
929
+ }
930
+ }
931
+ scene = null;
932
+ stats = null;
933
+ rendererIsShared = shareRenderer();
934
+ loadingElement = null;
935
+ async connectedCallback() {
936
+ this.addCSS(twisty3DVantageCSS);
937
+ this.addElement((await this.canvasInfo()).canvas);
938
+ void this.#onResize();
939
+ const observer = new ResizeObserver(this.#onResize.bind(this));
940
+ observer.observe(this.contentWrapper);
941
+ void this.orbitControls();
942
+ void this.#setupBasicPresses();
943
+ this.scheduleRender();
944
+ }
945
+ async #setupBasicPresses() {
946
+ const dragTracker = await this.#dragTracker();
947
+ dragTracker.addEventListener(
948
+ "press",
949
+ (async (e) => {
950
+ const movePressInput = await this.model.twistySceneModel.movePressInput.get();
951
+ if (movePressInput !== "basic") {
952
+ return;
953
+ }
954
+ this.dispatchEvent(
955
+ new CustomEvent("press", {
956
+ detail: {
957
+ pressInfo: e.detail,
958
+ cameraPromise: this.camera()
959
+ }
960
+ })
961
+ );
962
+ })
963
+ // TODO
964
+ );
965
+ }
966
+ #onResizeStaleDropper = new StaleDropper();
967
+ async clearCanvas() {
968
+ if (this.rendererIsShared) {
969
+ const canvasInfo = await this.canvasInfo();
970
+ canvasInfo.context.clearRect(
971
+ 0,
972
+ 0,
973
+ canvasInfo.canvas.width,
974
+ canvasInfo.canvas.height
975
+ );
976
+ } else {
977
+ const renderer = await this.renderer();
978
+ const context = renderer.getContext();
979
+ context.clear(context.COLOR_BUFFER_BIT);
980
+ }
981
+ }
982
+ // TODO: Why doesn't this work for the top-right back view height?
983
+ #width = 0;
984
+ #height = 0;
985
+ async #onResize() {
986
+ const camera = await this.#onResizeStaleDropper.queue(this.camera());
987
+ const w = this.contentWrapper.clientWidth;
988
+ const h = this.contentWrapper.clientHeight;
989
+ this.#width = w;
990
+ this.#height = h;
991
+ const off = 0;
992
+ let yoff = 0;
993
+ let excess = 0;
994
+ if (h > w) {
995
+ excess = h - w;
996
+ yoff = -Math.floor(0.5 * excess);
997
+ }
998
+ camera.aspect = w / h;
999
+ camera.setViewOffset(w, h - excess, off, yoff, w, h);
1000
+ camera.updateProjectionMatrix();
1001
+ void this.clearCanvas();
1002
+ if (this.rendererIsShared) {
1003
+ const canvasInfo = await this.canvasInfo();
1004
+ canvasInfo.canvas.width = w * pixelRatio();
1005
+ canvasInfo.canvas.height = h * pixelRatio();
1006
+ canvasInfo.canvas.style.width = `${w.toString()}px`;
1007
+ canvasInfo.canvas.style.height = `${h.toString()}px`;
1008
+ } else {
1009
+ const renderer = await this.renderer();
1010
+ renderer.setSize(w, h, true);
1011
+ }
1012
+ this.scheduleRender();
1013
+ }
1014
+ #cachedRenderer = null;
1015
+ async renderer() {
1016
+ if (this.rendererIsShared) {
1017
+ throw new Error("renderer expected to be shared.");
1018
+ }
1019
+ return this.#cachedRenderer ??= newRenderer();
1020
+ }
1021
+ #cachedCanvas = null;
1022
+ async canvasInfo() {
1023
+ return this.#cachedCanvas ??= (async () => {
1024
+ let canvas;
1025
+ if (this.rendererIsShared) {
1026
+ canvas = this.addElement(document.createElement("canvas"));
1027
+ } else {
1028
+ const renderer = await this.renderer();
1029
+ canvas = this.addElement(renderer.domElement);
1030
+ }
1031
+ this.loadingElement?.remove();
1032
+ const context = canvas.getContext("2d");
1033
+ return { canvas, context };
1034
+ })();
1035
+ }
1036
+ #cachedDragTracker = null;
1037
+ async #dragTracker() {
1038
+ return this.#cachedDragTracker ??= (async () => {
1039
+ const dragTracker = new DragTracker((await this.canvasInfo()).canvas);
1040
+ this.model?.twistySceneModel.dragInput.addFreshListener(
1041
+ (dragInputMode) => {
1042
+ let dragInputEnabled = false;
1043
+ switch (dragInputMode) {
1044
+ case "auto": {
1045
+ dragTracker.start();
1046
+ dragInputEnabled = true;
1047
+ break;
1048
+ }
1049
+ case "none": {
1050
+ dragTracker.stop();
1051
+ break;
1052
+ }
1053
+ }
1054
+ this.contentWrapper.classList.toggle(
1055
+ "drag-input-enabled",
1056
+ dragInputEnabled
1057
+ );
1058
+ }
1059
+ );
1060
+ return dragTracker;
1061
+ })();
1062
+ }
1063
+ #cachedCamera = null;
1064
+ async camera() {
1065
+ return this.#cachedCamera ??= (async () => {
1066
+ const camera = new (await bulk3DCode()).ThreePerspectiveCamera(
1067
+ 20,
1068
+ 1,
1069
+ // We rely on the resize logic to handle this.
1070
+ 0.1,
1071
+ 20
1072
+ );
1073
+ camera.position.copy(
1074
+ new (await bulk3DCode()).ThreeVector3(2, 4, 4).multiplyScalar(
1075
+ this.options?.backView ? -1 : 1
1076
+ )
1077
+ );
1078
+ camera.lookAt(0, 0, 0);
1079
+ return camera;
1080
+ })();
1081
+ }
1082
+ #cachedOrbitControls = null;
1083
+ async orbitControls() {
1084
+ return this.#cachedOrbitControls ??= (async () => {
1085
+ const orbitControls = new TwistyOrbitControls(
1086
+ this.model,
1087
+ !!this.options?.backView,
1088
+ (await this.canvasInfo()).canvas,
1089
+ await this.#dragTracker()
1090
+ );
1091
+ if (this.model) {
1092
+ this.addListener(
1093
+ this.model.twistySceneModel.orbitCoordinates,
1094
+ async (orbitCoordinates) => {
1095
+ const camera = await this.camera();
1096
+ void setCameraFromOrbitCoordinates(
1097
+ camera,
1098
+ orbitCoordinates,
1099
+ this.options?.backView
1100
+ );
1101
+ this.scheduleRender();
1102
+ }
1103
+ );
1104
+ }
1105
+ return orbitControls;
1106
+ })();
1107
+ }
1108
+ addListener(prop, listener) {
1109
+ prop.addFreshListener(listener);
1110
+ this.#disconnectionFunctions.push(() => {
1111
+ prop.removeFreshListener(listener);
1112
+ });
1113
+ }
1114
+ #disconnectionFunctions = [];
1115
+ disconnect() {
1116
+ for (const fn of this.#disconnectionFunctions) {
1117
+ fn();
1118
+ }
1119
+ this.#disconnectionFunctions = [];
1120
+ }
1121
+ #experimentalNextRenderFinishedCallback = null;
1122
+ experimentalNextRenderFinishedCallback(callback) {
1123
+ this.#experimentalNextRenderFinishedCallback = callback;
1124
+ }
1125
+ async render() {
1126
+ if (!this.scene) {
1127
+ throw new Error("Attempted to render without a scene");
1128
+ }
1129
+ this.stats?.begin();
1130
+ const [scene, camera, canvas] = await Promise.all([
1131
+ this.scene.scene(),
1132
+ this.camera(),
1133
+ this.canvasInfo()
1134
+ ]);
1135
+ if (this.rendererIsShared) {
1136
+ await renderPooled(
1137
+ this.#width,
1138
+ this.#height,
1139
+ canvas.canvas,
1140
+ scene,
1141
+ camera
1142
+ );
1143
+ } else {
1144
+ (await this.renderer()).render(scene, camera);
1145
+ }
1146
+ this.stats?.end();
1147
+ this.#experimentalNextRenderFinishedCallback?.();
1148
+ this.#experimentalNextRenderFinishedCallback = null;
1149
+ }
1150
+ #scheduler = new RenderScheduler(this.render.bind(this));
1151
+ scheduleRender() {
1152
+ this.#scheduler.requestAnimFrame();
1153
+ }
1154
+ };
1155
+ customElementsShim.define("twisty-3d-vantage", Twisty3DVantage);
1156
+
1157
+ export {
1158
+ setTwistyDebug,
1159
+ StaleDropper,
1160
+ TwistyPropSource,
1161
+ SimpleTwistyPropSource,
1162
+ NO_VALUE,
1163
+ TwistyPropDerived,
1164
+ FreshListenerManager,
1165
+ HTMLElementShim,
1166
+ customElementsShim,
1167
+ cssStyleSheetShim,
1168
+ ManagedCustomElement,
1169
+ RenderScheduler,
1170
+ hintFaceletStyles,
1171
+ HintFaceletProp,
1172
+ TAU,
1173
+ DEGREES_PER_RADIAN,
1174
+ rawRenderPooled,
1175
+ setCameraFromOrbitCoordinates,
1176
+ haveStartedSharingRenderers,
1177
+ Twisty3DVantage,
1178
+ bulk3DCode
1179
+ };
1180
+ //# sourceMappingURL=chunk-DQGYYYHZ.js.map