@twick/live-player 0.14.20 → 0.15.1

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.
@@ -1,2121 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
- class EventDispatcherBase {
6
- constructor() {
7
- this.subscribable = new Subscribable(this);
8
- this.subscribers = /* @__PURE__ */ new Set();
9
- }
10
- /**
11
- * {@inheritDoc Subscribable.subscribe}
12
- */
13
- subscribe(handler) {
14
- this.subscribers.add(handler);
15
- return () => this.unsubscribe(handler);
16
- }
17
- /**
18
- * {@inheritDoc Subscribable.unsubscribe}
19
- */
20
- unsubscribe(handler) {
21
- this.subscribers.delete(handler);
22
- }
23
- /**
24
- * Unsubscribe all subscribers from the event.
25
- */
26
- clear() {
27
- this.subscribers.clear();
28
- }
29
- notifySubscribers(value) {
30
- return [...this.subscribers].map((handler) => handler(value));
31
- }
32
- }
33
- class Subscribable {
34
- constructor(dispatcher) {
35
- this.dispatcher = dispatcher;
36
- }
37
- /**
38
- * Subscribe to the event.
39
- *
40
- * @param handler - The handler to invoke when the event occurs.
41
- *
42
- * @returns A callback function that cancels the subscription.
43
- */
44
- subscribe(handler) {
45
- return this.dispatcher.subscribe(handler);
46
- }
47
- /**
48
- * Unsubscribe from the event.
49
- *
50
- * @param handler - The handler to unsubscribe.
51
- */
52
- unsubscribe(handler) {
53
- this.dispatcher.unsubscribe(handler);
54
- }
55
- }
56
- class AsyncEventDispatcher extends EventDispatcherBase {
57
- async dispatch(value) {
58
- await Promise.all(this.notifySubscribers(value));
59
- }
60
- }
61
- class EventDispatcher extends EventDispatcherBase {
62
- dispatch(value) {
63
- this.notifySubscribers(value);
64
- }
65
- }
66
- class FlagDispatcher extends EventDispatcherBase {
67
- constructor() {
68
- super(...arguments);
69
- this.value = false;
70
- }
71
- /**
72
- * Notify all current and future subscribers.
73
- */
74
- raise() {
75
- if (!this.value) {
76
- this.value = true;
77
- this.notifySubscribers();
78
- }
79
- }
80
- /**
81
- * Stop notifying future subscribers.
82
- */
83
- reset() {
84
- this.value = false;
85
- }
86
- /**
87
- * Are subscribers being notified?
88
- */
89
- isRaised() {
90
- return this.value;
91
- }
92
- subscribe(handler) {
93
- const unsubscribe = super.subscribe(handler);
94
- if (this.value) {
95
- handler();
96
- }
97
- return unsubscribe;
98
- }
99
- }
100
- class ValueDispatcher extends EventDispatcherBase {
101
- /**
102
- * {@inheritDoc SubscribableValueEvent.current}
103
- */
104
- get current() {
105
- return this.value;
106
- }
107
- /**
108
- * Set the current value of this dispatcher.
109
- *
110
- * @remarks
111
- * Setting the value will immediately notify all subscribers.
112
- *
113
- * @param value - The new value.
114
- */
115
- set current(value) {
116
- this.value = value;
117
- this.notifySubscribers(value);
118
- }
119
- /**
120
- * @param value - The initial value.
121
- */
122
- constructor(value) {
123
- super();
124
- this.value = value;
125
- this.subscribable = new SubscribableValueEvent(this);
126
- }
127
- /**
128
- * {@inheritDoc SubscribableValueEvent.subscribe}
129
- */
130
- subscribe(handler, dispatchImmediately = true) {
131
- const unsubscribe = super.subscribe(handler);
132
- if (dispatchImmediately) {
133
- handler(this.value);
134
- }
135
- return unsubscribe;
136
- }
137
- }
138
- class SubscribableValueEvent extends Subscribable {
139
- /**
140
- * Get the most recent value of this dispatcher.
141
- */
142
- get current() {
143
- return this.dispatcher.current;
144
- }
145
- /**
146
- * Subscribe to the event.
147
- *
148
- * Subscribing will immediately invoke the handler with the most recent value.
149
- *
150
- * @param handler - The handler to invoke when the event occurs.
151
- * @param dispatchImmediately - Whether the handler should be immediately
152
- * invoked with the most recent value.
153
- *
154
- * @returns Callback function that cancels the subscription.
155
- */
156
- subscribe(handler, dispatchImmediately = true) {
157
- return this.dispatcher.subscribe(handler, dispatchImmediately);
158
- }
159
- }
160
- function map(from, to, value) {
161
- return from + (to - from) * value;
162
- }
163
- function clamp(min, max, value) {
164
- return value < min ? min : value > max ? max : value;
165
- }
166
- const SceneStack = [];
167
- function useLogger() {
168
- var _a;
169
- return ((_a = SceneStack.at(-1)) == null ? void 0 : _a.logger) ?? console;
170
- }
171
- class DetailedError extends Error {
172
- constructor(props, remarks) {
173
- if (typeof props === "string") {
174
- super(props);
175
- this.remarks = remarks;
176
- } else {
177
- super(props.message);
178
- this.remarks = props.remarks;
179
- this.object = props.object;
180
- this.durationMs = props.durationMs;
181
- this.inspect = props.inspect;
182
- }
183
- }
184
- }
185
- const ThreadStack = [];
186
- function useThread() {
187
- const thread = ThreadStack.at(-1);
188
- if (!thread) {
189
- throw new DetailedError(
190
- "The thread is not available in the current context.",
191
- // language=markdown
192
- `\`useThread()\` can only be called from within generator functions.
193
- It's not available during rendering.`
194
- );
195
- }
196
- return thread;
197
- }
198
- function errorToLog(error) {
199
- return {
200
- message: error.message,
201
- stack: error.stack,
202
- remarks: error.remarks
203
- };
204
- }
205
- function getContext(options, canvas = document.createElement("canvas")) {
206
- const context = canvas.getContext("2d", options);
207
- if (!context) {
208
- throw new Error("Could not create a 2D context.");
209
- }
210
- return context;
211
- }
212
- const RAD2DEG = 180 / Math.PI;
213
- const DEG2RAD = Math.PI / 180;
214
- class Semaphore {
215
- constructor() {
216
- this.resolveCurrent = null;
217
- this.current = null;
218
- }
219
- async acquire() {
220
- while (this.current) {
221
- await this.current;
222
- }
223
- this.current = new Promise((resolve) => {
224
- this.resolveCurrent = resolve;
225
- });
226
- }
227
- release() {
228
- var _a;
229
- this.current = null;
230
- (_a = this.resolveCurrent) == null ? void 0 : _a.call(this);
231
- this.resolveCurrent = null;
232
- }
233
- }
234
- const PlaybackStack = [];
235
- function usePlayback() {
236
- const playback = PlaybackStack.at(-1);
237
- if (!playback) {
238
- throw new Error("The playback is not available in the current context.");
239
- }
240
- return playback;
241
- }
242
- function arcLerp(value, reverse, ratio) {
243
- let flip = reverse;
244
- if (ratio > 1) {
245
- ratio = 1 / ratio;
246
- } else {
247
- flip = !flip;
248
- }
249
- const normalized = flip ? Math.acos(clamp(-1, 1, 1 - value)) : Math.asin(value);
250
- const radians = map(normalized, map(0, Math.PI / 2, value), ratio);
251
- let xValue = Math.sin(radians);
252
- let yValue = 1 - Math.cos(radians);
253
- if (reverse) {
254
- [xValue, yValue] = [yValue, xValue];
255
- }
256
- return { x: xValue, y: yValue };
257
- }
258
- function decorate(fn, ...decorators) {
259
- const target = { [fn.name]: fn };
260
- const descriptor = Object.getOwnPropertyDescriptor(target, fn.name);
261
- if (descriptor) {
262
- for (let i = decorators.length - 1; i >= 0; i--) {
263
- decorators[i](target, fn.name, descriptor);
264
- }
265
- }
266
- }
267
- function threadable(customName) {
268
- return function(_, propertyKey, descriptor) {
269
- descriptor.value.prototype.name = propertyKey;
270
- descriptor.value.prototype.threadable = true;
271
- };
272
- }
273
- function easeInOutCubic(value, from = 0, to = 1) {
274
- value = value < 0.5 ? 4 * value * value * value : 1 - Math.pow(-2 * value + 2, 3) / 2;
275
- return map(from, to, value);
276
- }
277
- decorate(tween, threadable());
278
- function* tween(seconds, onProgress, onEnd) {
279
- const thread = useThread();
280
- const startTime = thread.time();
281
- const endTime = thread.time() + seconds;
282
- onProgress(0, 0);
283
- while (endTime > thread.fixed) {
284
- const time = thread.fixed - startTime;
285
- const value = time / seconds;
286
- if (time > 0) {
287
- onProgress(value, time);
288
- }
289
- yield;
290
- }
291
- thread.time(endTime);
292
- onProgress(1, seconds);
293
- onEnd == null ? void 0 : onEnd(1, seconds);
294
- }
295
- var Direction;
296
- (function(Direction2) {
297
- Direction2[Direction2["Top"] = 4] = "Top";
298
- Direction2[Direction2["Bottom"] = 8] = "Bottom";
299
- Direction2[Direction2["Left"] = 16] = "Left";
300
- Direction2[Direction2["Right"] = 32] = "Right";
301
- })(Direction || (Direction = {}));
302
- var Center;
303
- (function(Center2) {
304
- Center2[Center2["Vertical"] = 1] = "Vertical";
305
- Center2[Center2["Horizontal"] = 2] = "Horizontal";
306
- })(Center || (Center = {}));
307
- var Origin;
308
- (function(Origin2) {
309
- Origin2[Origin2["Middle"] = 3] = "Middle";
310
- Origin2[Origin2["Top"] = 5] = "Top";
311
- Origin2[Origin2["Bottom"] = 9] = "Bottom";
312
- Origin2[Origin2["Left"] = 18] = "Left";
313
- Origin2[Origin2["Right"] = 34] = "Right";
314
- Origin2[Origin2["TopLeft"] = 20] = "TopLeft";
315
- Origin2[Origin2["TopRight"] = 36] = "TopRight";
316
- Origin2[Origin2["BottomLeft"] = 24] = "BottomLeft";
317
- Origin2[Origin2["BottomRight"] = 40] = "BottomRight";
318
- })(Origin || (Origin = {}));
319
- decorate(waitFor, threadable());
320
- function* waitFor(seconds = 0, after) {
321
- const thread = useThread();
322
- const step = usePlayback().framesToSeconds(1);
323
- const targetTime = thread.time() + seconds;
324
- while (targetTime - step > thread.fixed) {
325
- yield;
326
- }
327
- thread.time(targetTime);
328
- if (after) {
329
- yield* after;
330
- }
331
- }
332
- function setTaskName(task, source) {
333
- const prototype = Object.getPrototypeOf(task);
334
- if (!prototype.threadable) {
335
- prototype.threadable = true;
336
- prototype.name = typeof source === "string" ? source : getTaskName(source);
337
- }
338
- }
339
- function getTaskName(task) {
340
- return Object.getPrototypeOf(task).name ?? null;
341
- }
342
- function run(firstArg, runner) {
343
- let task;
344
- if (typeof firstArg === "string") {
345
- task = runner();
346
- setTaskName(task, firstArg);
347
- } else {
348
- task = firstArg();
349
- setTaskName(task, task);
350
- }
351
- return task;
352
- }
353
- class DependencyContext {
354
- static collectPromise(promise, initialValue = null) {
355
- const handle = {
356
- promise,
357
- value: initialValue,
358
- stack: new Error().stack
359
- };
360
- const context = this.collectionStack.at(-1);
361
- if (context) {
362
- handle.owner = context.owner;
363
- }
364
- promise.then((value) => {
365
- handle.value = value;
366
- context == null ? void 0 : context.markDirty();
367
- });
368
- this.promises.push(handle);
369
- return handle;
370
- }
371
- static hasPromises() {
372
- return this.promises.length > 0;
373
- }
374
- static async consumePromises() {
375
- const promises = [...this.promises];
376
- await Promise.all(promises.map((handle) => handle.promise));
377
- this.promises = this.promises.filter((v) => !promises.includes(v));
378
- return promises;
379
- }
380
- constructor(owner) {
381
- this.owner = owner;
382
- this.dependencies = /* @__PURE__ */ new Set();
383
- this.event = new FlagDispatcher();
384
- this.markDirty = () => this.event.raise();
385
- this.invokable = this.invoke.bind(this);
386
- Object.defineProperty(this.invokable, "context", {
387
- value: this
388
- });
389
- Object.defineProperty(this.invokable, "toPromise", {
390
- value: this.toPromise.bind(this)
391
- });
392
- }
393
- invoke() {
394
- }
395
- startCollecting() {
396
- if (DependencyContext.collectionSet.has(this)) {
397
- throw new DetailedError("A circular dependency occurred between signals.", `This can happen when signals reference each other in a loop.
398
- Try using the attached stack trace to locate said loop.`);
399
- }
400
- DependencyContext.collectionSet.add(this);
401
- DependencyContext.collectionStack.push(this);
402
- }
403
- finishCollecting() {
404
- DependencyContext.collectionSet.delete(this);
405
- if (DependencyContext.collectionStack.pop() !== this) {
406
- throw new Error("collectStart/collectEnd was called out of order.");
407
- }
408
- }
409
- clearDependencies() {
410
- this.dependencies.forEach((dep) => dep.unsubscribe(this.markDirty));
411
- this.dependencies.clear();
412
- }
413
- collect() {
414
- const signal = DependencyContext.collectionStack.at(-1);
415
- if (signal) {
416
- signal.dependencies.add(this.event.subscribable);
417
- this.event.subscribe(signal.markDirty);
418
- }
419
- }
420
- dispose() {
421
- this.clearDependencies();
422
- this.event.clear();
423
- this.owner = null;
424
- }
425
- async toPromise() {
426
- do {
427
- await DependencyContext.consumePromises();
428
- this.invokable();
429
- } while (DependencyContext.hasPromises());
430
- return this.invokable;
431
- }
432
- }
433
- DependencyContext.collectionSet = /* @__PURE__ */ new Set();
434
- DependencyContext.collectionStack = [];
435
- DependencyContext.promises = [];
436
- const DEFAULT = Symbol.for("@twick/core/signals/default");
437
- function isReactive(value) {
438
- return typeof value === "function";
439
- }
440
- function modify(value, modification) {
441
- return isReactive(value) ? () => modification(value()) : modification(value);
442
- }
443
- function unwrap(value) {
444
- return isReactive(value) ? value() : value;
445
- }
446
- class SignalContext extends DependencyContext {
447
- constructor(initial, interpolation, owner = void 0, parser = (value) => value, extensions = {}) {
448
- super(owner);
449
- this.initial = initial;
450
- this.interpolation = interpolation;
451
- this.parser = parser;
452
- this.tweening = false;
453
- Object.defineProperty(this.invokable, "reset", {
454
- value: this.reset.bind(this)
455
- });
456
- Object.defineProperty(this.invokable, "save", {
457
- value: this.save.bind(this)
458
- });
459
- Object.defineProperty(this.invokable, "isInitial", {
460
- value: this.isInitial.bind(this)
461
- });
462
- if (this.initial !== void 0) {
463
- this.current = this.initial;
464
- this.markDirty();
465
- if (!isReactive(this.initial)) {
466
- this.last = this.parse(this.initial);
467
- }
468
- }
469
- this.extensions = {
470
- getter: this.getter.bind(this),
471
- setter: this.setter.bind(this),
472
- tweener: this.tweener.bind(this),
473
- ...extensions
474
- };
475
- }
476
- toSignal() {
477
- return this.invokable;
478
- }
479
- parse(value) {
480
- return this.parser(value);
481
- }
482
- set(value) {
483
- this.extensions.setter(value);
484
- return this.owner;
485
- }
486
- setter(value) {
487
- if (value === DEFAULT) {
488
- value = this.initial;
489
- }
490
- if (this.current === value) {
491
- return this.owner;
492
- }
493
- this.current = value;
494
- this.markDirty();
495
- this.clearDependencies();
496
- if (!isReactive(value)) {
497
- this.last = this.parse(value);
498
- }
499
- return this.owner;
500
- }
501
- get() {
502
- return this.extensions.getter();
503
- }
504
- getter() {
505
- var _a;
506
- if (this.event.isRaised() && isReactive(this.current)) {
507
- this.clearDependencies();
508
- this.startCollecting();
509
- try {
510
- this.last = this.parse(this.current());
511
- } catch (e) {
512
- useLogger().error({
513
- ...errorToLog(e),
514
- inspect: (_a = this.owner) == null ? void 0 : _a.key
515
- });
516
- }
517
- this.finishCollecting();
518
- }
519
- this.event.reset();
520
- this.collect();
521
- return this.last;
522
- }
523
- invoke(value, duration, timingFunction = easeInOutCubic, interpolationFunction = this.interpolation) {
524
- if (value === void 0) {
525
- return this.get();
526
- }
527
- if (duration === void 0) {
528
- return this.set(value);
529
- }
530
- const queue = this.createQueue(timingFunction, interpolationFunction);
531
- return queue.to(value, duration);
532
- }
533
- createQueue(defaultTimingFunction, defaultInterpolationFunction) {
534
- const initial = this.get();
535
- const queue = [];
536
- const task = run("animation chain", function* animate() {
537
- while (queue.length > 0) {
538
- yield* queue.shift();
539
- }
540
- });
541
- task.to = (value, duration, timingFunction = defaultTimingFunction, interpolationFunction = defaultInterpolationFunction) => {
542
- defaultTimingFunction = timingFunction;
543
- defaultInterpolationFunction = interpolationFunction;
544
- queue.push(this.tween(value, duration, timingFunction, interpolationFunction));
545
- return task;
546
- };
547
- task.back = (time, timingFunction = defaultTimingFunction, interpolationFunction = defaultInterpolationFunction) => {
548
- defaultTimingFunction = timingFunction;
549
- defaultInterpolationFunction = interpolationFunction;
550
- queue.push(this.tween(initial, time, defaultTimingFunction, defaultInterpolationFunction));
551
- return task;
552
- };
553
- task.wait = (duration) => {
554
- queue.push(waitFor(duration));
555
- return task;
556
- };
557
- task.run = (generator) => {
558
- queue.push(generator);
559
- return task;
560
- };
561
- task.do = (callback) => {
562
- queue.push(run(function* () {
563
- callback();
564
- }));
565
- return task;
566
- };
567
- return task;
568
- }
569
- *tween(value, duration, timingFunction, interpolationFunction) {
570
- if (value === DEFAULT) {
571
- value = this.initial;
572
- }
573
- this.tweening = true;
574
- yield* this.extensions.tweener(value, duration, timingFunction, interpolationFunction);
575
- this.set(value);
576
- this.tweening = false;
577
- }
578
- *tweener(value, duration, timingFunction, interpolationFunction) {
579
- const from = this.get();
580
- yield* tween(duration, (v) => {
581
- this.set(interpolationFunction(from, this.parse(unwrap(value)), timingFunction(v)));
582
- });
583
- }
584
- dispose() {
585
- super.dispose();
586
- this.initial = void 0;
587
- this.current = void 0;
588
- this.last = void 0;
589
- }
590
- /**
591
- * Reset the signal to its initial value (if one has been set).
592
- *
593
- * @example
594
- * ```ts
595
- * const signal = createSignal(7);
596
- *
597
- * signal.reset();
598
- * // same as:
599
- * signal(7);
600
- * ```
601
- */
602
- reset() {
603
- if (this.initial !== void 0) {
604
- this.set(this.initial);
605
- }
606
- return this.owner;
607
- }
608
- /**
609
- * Compute the current value of the signal and immediately set it.
610
- *
611
- * @remarks
612
- * This method can be used to stop the signal from updating while keeping its
613
- * current value.
614
- *
615
- * @example
616
- * ```ts
617
- * signal.save();
618
- * // same as:
619
- * signal(signal());
620
- * ```
621
- */
622
- save() {
623
- return this.set(this.get());
624
- }
625
- /**
626
- * Check if the signal is currently using its initial value.
627
- *
628
- * @example
629
- * ```ts
630
- *
631
- * const signal = createSignal(0);
632
- * signal.isInitial(); // true
633
- *
634
- * signal(5);
635
- * signal.isInitial(); // false
636
- *
637
- * signal(DEFAULT);
638
- * signal.isInitial(); // true
639
- * ```
640
- */
641
- isInitial() {
642
- this.collect();
643
- return this.current === this.initial;
644
- }
645
- /**
646
- * Get the initial value of this signal.
647
- */
648
- getInitial() {
649
- return this.initial;
650
- }
651
- /**
652
- * Get the raw value of this signal.
653
- *
654
- * @remarks
655
- * If the signal was provided with a factory function, the function itself
656
- * will be returned, without invoking it.
657
- *
658
- * This method can be used to create copies of signals.
659
- *
660
- * @example
661
- * ```ts
662
- * const a = createSignal(2);
663
- * const b = createSignal(() => a);
664
- * // b() == 2
665
- *
666
- * const bClone = createSignal(b.raw());
667
- * // bClone() == 2
668
- *
669
- * a(4);
670
- * // b() == 4
671
- * // bClone() == 4
672
- * ```
673
- */
674
- raw() {
675
- return this.current;
676
- }
677
- /**
678
- * Is the signal undergoing a tween?
679
- */
680
- isTweening() {
681
- return this.tweening;
682
- }
683
- }
684
- class CompoundSignalContext extends SignalContext {
685
- constructor(entries, parser, initial, interpolation, owner = void 0, extensions = {}) {
686
- var _a;
687
- super(void 0, interpolation, owner, parser, extensions);
688
- this.entries = entries;
689
- this.signals = [];
690
- this.parser = parser;
691
- for (const entry of entries) {
692
- let key;
693
- let signal;
694
- if (Array.isArray(entry)) {
695
- [key, signal] = entry;
696
- (_a = signal.context).owner ?? (_a.owner = this);
697
- } else {
698
- key = entry;
699
- signal = new SignalContext(modify(initial, (value) => parser(value)[entry]), map, owner ?? this.invokable).toSignal();
700
- }
701
- this.signals.push([key, signal]);
702
- Object.defineProperty(this.invokable, key, { value: signal });
703
- }
704
- }
705
- toSignal() {
706
- return this.invokable;
707
- }
708
- parse(value) {
709
- return this.parser(value);
710
- }
711
- getter() {
712
- return this.parse(Object.fromEntries(this.signals.map(([key, property]) => [key, property()])));
713
- }
714
- setter(value) {
715
- if (isReactive(value)) {
716
- for (const [key, property] of this.signals) {
717
- property(() => this.parser(value())[key]);
718
- }
719
- } else {
720
- const parsed = this.parse(value);
721
- for (const [key, property] of this.signals) {
722
- property(parsed[key]);
723
- }
724
- }
725
- return this.owner;
726
- }
727
- reset() {
728
- for (const [, signal] of this.signals) {
729
- signal.reset();
730
- }
731
- return this.owner;
732
- }
733
- save() {
734
- for (const [, signal] of this.signals) {
735
- signal.save();
736
- }
737
- return this.owner;
738
- }
739
- isInitial() {
740
- for (const [, signal] of this.signals) {
741
- if (!signal.isInitial()) {
742
- return false;
743
- }
744
- }
745
- return true;
746
- }
747
- raw() {
748
- return Object.fromEntries(this.signals.map(([key, property]) => [key, property.context.raw()]));
749
- }
750
- }
751
- const EPSILON = 1e-6;
752
- class Vector2 {
753
- static createSignal(initial, interpolation = Vector2.lerp, owner) {
754
- return new CompoundSignalContext(["x", "y"], (value) => new Vector2(value), initial, interpolation, owner).toSignal();
755
- }
756
- static lerp(from, to, value) {
757
- let valueX;
758
- let valueY;
759
- if (typeof value === "number") {
760
- valueX = valueY = value;
761
- } else {
762
- valueX = value.x;
763
- valueY = value.y;
764
- }
765
- return new Vector2(map(from.x, to.x, valueX), map(from.y, to.y, valueY));
766
- }
767
- static arcLerp(from, to, value, reverse = false, ratio) {
768
- ratio ?? (ratio = from.sub(to).ctg);
769
- return Vector2.lerp(from, to, new Vector2(arcLerp(value, reverse, ratio)));
770
- }
771
- static createArcLerp(reverse, ratio) {
772
- return (from, to, value) => Vector2.arcLerp(from, to, value, reverse, ratio);
773
- }
774
- /**
775
- * Interpolates between two vectors on the polar plane by interpolating
776
- * the angles and magnitudes of the vectors individually.
777
- *
778
- * @param from - The starting vector.
779
- * @param to - The target vector.
780
- * @param value - The t-value of the interpolation.
781
- * @param counterclockwise - Whether the vector should get rotated
782
- * counterclockwise. Defaults to `false`.
783
- * @param origin - The center of rotation. Defaults to the origin.
784
- *
785
- * @remarks
786
- * This function is useful when used in conjunction with {@link rotate} to
787
- * animate an object's position on a circular arc (see examples).
788
- *
789
- * @example
790
- * Animating an object in a circle around the origin
791
- * ```tsx
792
- * circle().position(
793
- * circle().position().rotate(180),
794
- * 1,
795
- * easeInOutCubic,
796
- * Vector2.polarLerp
797
- * );
798
- * ```
799
- * @example
800
- * Rotating an object around the point `[-200, 100]`
801
- * ```ts
802
- * circle().position(
803
- * circle().position().rotate(180, [-200, 100]),
804
- * 1,
805
- * easeInOutCubic,
806
- * Vector2.createPolarLerp(false, [-200, 100]),
807
- * );
808
- * ```
809
- * @example
810
- * Rotating an object counterclockwise around the origin
811
- * ```ts
812
- * circle().position(
813
- * circle().position().rotate(180),
814
- * 1,
815
- * easeInOutCubic,
816
- * Vector2.createPolarLerp(true),
817
- * );
818
- * ```
819
- */
820
- static polarLerp(from, to, value, counterclockwise = false, origin = Vector2.zero) {
821
- from = from.sub(origin);
822
- to = to.sub(origin);
823
- const fromAngle = from.degrees;
824
- let toAngle = to.degrees;
825
- const isCounterclockwise = fromAngle > toAngle;
826
- if (isCounterclockwise !== counterclockwise) {
827
- toAngle = toAngle + (counterclockwise ? -360 : 360);
828
- }
829
- const angle = map(fromAngle, toAngle, value) * DEG2RAD;
830
- const magnitude = map(from.magnitude, to.magnitude, value);
831
- return new Vector2(magnitude * Math.cos(angle) + origin.x, magnitude * Math.sin(angle) + origin.y);
832
- }
833
- /**
834
- * Helper function to create a {@link Vector2.polarLerp} interpolation
835
- * function with additional parameters.
836
- *
837
- * @param counterclockwise - Whether the point should get rotated
838
- * counterclockwise.
839
- * @param center - The center of rotation. Defaults to the origin.
840
- */
841
- static createPolarLerp(counterclockwise = false, center = Vector2.zero) {
842
- return (from, to, value) => Vector2.polarLerp(from, to, value, counterclockwise, new Vector2(center));
843
- }
844
- static fromOrigin(origin) {
845
- const position = new Vector2();
846
- if (origin === Origin.Middle) {
847
- return position;
848
- }
849
- if (origin & Direction.Left) {
850
- position.x = -1;
851
- } else if (origin & Direction.Right) {
852
- position.x = 1;
853
- }
854
- if (origin & Direction.Top) {
855
- position.y = -1;
856
- } else if (origin & Direction.Bottom) {
857
- position.y = 1;
858
- }
859
- return position;
860
- }
861
- static fromScalar(value) {
862
- return new Vector2(value, value);
863
- }
864
- static fromRadians(radians) {
865
- return new Vector2(Math.cos(radians), Math.sin(radians));
866
- }
867
- static fromDegrees(degrees) {
868
- return Vector2.fromRadians(degrees * DEG2RAD);
869
- }
870
- /**
871
- * Return the angle in radians between the vector described by x and y and the
872
- * positive x-axis.
873
- *
874
- * @param x - The x component of the vector.
875
- * @param y - The y component of the vector.
876
- */
877
- static radians(x, y) {
878
- return Math.atan2(y, x);
879
- }
880
- /**
881
- * Return the angle in degrees between the vector described by x and y and the
882
- * positive x-axis.
883
- *
884
- * @param x - The x component of the vector.
885
- * @param y - The y component of the vector.
886
- *
887
- * @remarks
888
- * The returned angle will be between -180 and 180 degrees.
889
- */
890
- static degrees(x, y) {
891
- return Vector2.radians(x, y) * RAD2DEG;
892
- }
893
- static magnitude(x, y) {
894
- return Math.sqrt(x * x + y * y);
895
- }
896
- static squaredMagnitude(x, y) {
897
- return x * x + y * y;
898
- }
899
- static angleBetween(u, v) {
900
- return Math.acos(clamp(-1, 1, u.dot(v) / (u.magnitude * v.magnitude))) * (u.cross(v) >= 0 ? 1 : -1);
901
- }
902
- get width() {
903
- return this.x;
904
- }
905
- set width(value) {
906
- this.x = value;
907
- }
908
- get height() {
909
- return this.y;
910
- }
911
- set height(value) {
912
- this.y = value;
913
- }
914
- get magnitude() {
915
- return Vector2.magnitude(this.x, this.y);
916
- }
917
- get squaredMagnitude() {
918
- return Vector2.squaredMagnitude(this.x, this.y);
919
- }
920
- get normalized() {
921
- return this.scale(1 / Vector2.magnitude(this.x, this.y));
922
- }
923
- get safe() {
924
- return new Vector2(isNaN(this.x) ? 0 : this.x, isNaN(this.y) ? 0 : this.y);
925
- }
926
- get flipped() {
927
- return new Vector2(-this.x, -this.y);
928
- }
929
- get floored() {
930
- return new Vector2(Math.floor(this.x), Math.floor(this.y));
931
- }
932
- get perpendicular() {
933
- return new Vector2(this.y, -this.x);
934
- }
935
- /**
936
- * Return the angle in radians between the vector and the positive x-axis.
937
- */
938
- get radians() {
939
- return Vector2.radians(this.x, this.y);
940
- }
941
- /**
942
- * Return the angle in degrees between the vector and the positive x-axis.
943
- *
944
- * @remarks
945
- * The returned angle will be between -180 and 180 degrees.
946
- */
947
- get degrees() {
948
- return Vector2.degrees(this.x, this.y);
949
- }
950
- get ctg() {
951
- return this.x / this.y;
952
- }
953
- constructor(one, two) {
954
- this.x = 0;
955
- this.y = 0;
956
- if (one === void 0 || one === null) {
957
- return;
958
- }
959
- if (typeof one !== "object") {
960
- this.x = one;
961
- this.y = two ?? one;
962
- return;
963
- }
964
- if (Array.isArray(one)) {
965
- this.x = one[0];
966
- this.y = one[1];
967
- return;
968
- }
969
- if ("width" in one) {
970
- this.x = one.width;
971
- this.y = one.height;
972
- return;
973
- }
974
- this.x = one.x;
975
- this.y = one.y;
976
- }
977
- lerp(to, value) {
978
- return Vector2.lerp(this, to, value);
979
- }
980
- getOriginOffset(origin) {
981
- const offset = Vector2.fromOrigin(origin);
982
- offset.x *= this.x / 2;
983
- offset.y *= this.y / 2;
984
- return offset;
985
- }
986
- scale(value) {
987
- return new Vector2(this.x * value, this.y * value);
988
- }
989
- mul(possibleVector) {
990
- const vector = new Vector2(possibleVector);
991
- return new Vector2(this.x * vector.x, this.y * vector.y);
992
- }
993
- div(possibleVector) {
994
- const vector = new Vector2(possibleVector);
995
- return new Vector2(this.x / vector.x, this.y / vector.y);
996
- }
997
- add(possibleVector) {
998
- const vector = new Vector2(possibleVector);
999
- return new Vector2(this.x + vector.x, this.y + vector.y);
1000
- }
1001
- sub(possibleVector) {
1002
- const vector = new Vector2(possibleVector);
1003
- return new Vector2(this.x - vector.x, this.y - vector.y);
1004
- }
1005
- dot(possibleVector) {
1006
- const vector = new Vector2(possibleVector);
1007
- return this.x * vector.x + this.y * vector.y;
1008
- }
1009
- cross(possibleVector) {
1010
- const vector = new Vector2(possibleVector);
1011
- return this.x * vector.y - this.y * vector.x;
1012
- }
1013
- mod(possibleVector) {
1014
- const vector = new Vector2(possibleVector);
1015
- return new Vector2(this.x % vector.x, this.y % vector.y);
1016
- }
1017
- addX(value) {
1018
- return new Vector2(this.x + value, this.y);
1019
- }
1020
- addY(value) {
1021
- return new Vector2(this.x, this.y + value);
1022
- }
1023
- toSymbol() {
1024
- return Vector2.symbol;
1025
- }
1026
- toString() {
1027
- return `Vector2(${this.x}, ${this.y})`;
1028
- }
1029
- toUniform(gl, location) {
1030
- gl.uniform2f(location, this.x, this.y);
1031
- }
1032
- serialize() {
1033
- return { x: this.x, y: this.y };
1034
- }
1035
- /**
1036
- * Check if two vectors are exactly equal to each other.
1037
- *
1038
- * @remarks
1039
- * If you need to compensate for floating point inaccuracies, use the
1040
- * {@link equals} method, instead.
1041
- *
1042
- * @param other - The vector to compare.
1043
- */
1044
- exactlyEquals(other) {
1045
- return this.x === other.x && this.y === other.y;
1046
- }
1047
- /**
1048
- * Check if two vectors are equal to each other.
1049
- *
1050
- * @remarks
1051
- * This method allows passing an allowed error margin when comparing vectors
1052
- * to compensate for floating point inaccuracies. To check if two vectors are
1053
- * exactly equal, use the {@link exactlyEquals} method, instead.
1054
- *
1055
- * @param other - The vector to compare.
1056
- * @param threshold - The allowed error threshold when comparing the vectors.
1057
- */
1058
- equals(other, threshold = EPSILON) {
1059
- return Math.abs(this.x - other.x) <= threshold + Number.EPSILON && Math.abs(this.y - other.y) <= threshold + Number.EPSILON;
1060
- }
1061
- }
1062
- Vector2.symbol = Symbol.for("@twick/core/types/Vector2");
1063
- Vector2.zero = new Vector2();
1064
- Vector2.one = new Vector2(1, 1);
1065
- Vector2.right = new Vector2(1, 0);
1066
- Vector2.left = new Vector2(-1, 0);
1067
- Vector2.up = new Vector2(0, 1);
1068
- Vector2.down = new Vector2(0, -1);
1069
- Vector2.top = new Vector2(0, -1);
1070
- Vector2.bottom = new Vector2(0, 1);
1071
- Vector2.topLeft = new Vector2(-1, -1);
1072
- Vector2.topRight = new Vector2(1, -1);
1073
- Vector2.bottomLeft = new Vector2(-1, 1);
1074
- Vector2.bottomRight = new Vector2(1, 1);
1075
- var PlaybackState;
1076
- (function(PlaybackState2) {
1077
- PlaybackState2[PlaybackState2["Playing"] = 0] = "Playing";
1078
- PlaybackState2[PlaybackState2["Rendering"] = 1] = "Rendering";
1079
- PlaybackState2[PlaybackState2["Paused"] = 2] = "Paused";
1080
- PlaybackState2[PlaybackState2["Presenting"] = 3] = "Presenting";
1081
- })(PlaybackState || (PlaybackState = {}));
1082
- class PlaybackManager {
1083
- constructor() {
1084
- this.frame = 0;
1085
- this.speed = 1;
1086
- this.fps = 30;
1087
- this.duration = 0;
1088
- this.finished = false;
1089
- this.slides = [];
1090
- this.previousScene = null;
1091
- this.state = PlaybackState.Paused;
1092
- this.currentSceneReference = null;
1093
- this.scenes = new ValueDispatcher([]);
1094
- }
1095
- /**
1096
- * Triggered when the active scene changes.
1097
- *
1098
- * @eventProperty
1099
- */
1100
- get onSceneChanged() {
1101
- if (this.currentSceneReference === null) {
1102
- throw new Error("PlaybackManager has not been properly initialized");
1103
- }
1104
- return this.currentSceneReference.subscribable;
1105
- }
1106
- /**
1107
- * Triggered when the scenes get recalculated.
1108
- *
1109
- * @remarks
1110
- * This event indicates that the timing of at least one scene has changed.
1111
- *
1112
- * @eventProperty
1113
- */
1114
- get onScenesRecalculated() {
1115
- return this.scenes.subscribable;
1116
- }
1117
- get currentScene() {
1118
- if (this.currentSceneReference === null) {
1119
- throw new Error("PlaybackManager has not been properly initialized");
1120
- }
1121
- return this.currentSceneReference.current;
1122
- }
1123
- set currentScene(scene) {
1124
- if (!scene) {
1125
- throw new Error("Invalid scene.");
1126
- }
1127
- this.currentSceneReference ?? (this.currentSceneReference = new ValueDispatcher(scene));
1128
- this.currentSceneReference.current = scene;
1129
- }
1130
- setup(scenes) {
1131
- this.scenes.current = scenes;
1132
- this.currentScene = scenes[0];
1133
- }
1134
- async progress() {
1135
- this.finished = await this.next();
1136
- return this.finished;
1137
- }
1138
- async seek(frame) {
1139
- if (frame <= this.frame || this.currentScene.isCached() && this.currentScene.lastFrame < frame) {
1140
- const scene = this.findBestScene(frame);
1141
- if (scene !== this.currentScene) {
1142
- this.currentScene.stopAllMedia();
1143
- this.previousScene = null;
1144
- this.currentScene = scene;
1145
- this.frame = this.currentScene.firstFrame;
1146
- await this.currentScene.reset();
1147
- } else if (this.frame >= frame) {
1148
- this.previousScene = null;
1149
- this.frame = this.currentScene.firstFrame;
1150
- await this.currentScene.reset();
1151
- }
1152
- }
1153
- this.finished = false;
1154
- while (this.frame < frame && !this.finished) {
1155
- this.finished = await this.next();
1156
- }
1157
- return this.finished;
1158
- }
1159
- async reset() {
1160
- this.previousScene = null;
1161
- this.currentScene = this.scenes.current[0];
1162
- this.frame = 0;
1163
- await this.currentScene.reset();
1164
- }
1165
- reload(description) {
1166
- this.scenes.current.forEach((scene) => scene.reload(description));
1167
- }
1168
- async recalculate() {
1169
- this.previousScene = null;
1170
- this.slides = [];
1171
- const speed = this.speed;
1172
- this.frame = 0;
1173
- this.speed = 1;
1174
- const scenes = [];
1175
- try {
1176
- for (const scene of this.scenes.current) {
1177
- await scene.recalculate((frame) => {
1178
- this.frame = frame;
1179
- });
1180
- this.slides.push(...scene.slides.onChanged.current);
1181
- scenes.push(scene);
1182
- }
1183
- } finally {
1184
- this.speed = speed;
1185
- }
1186
- this.scenes.current = scenes;
1187
- this.duration = this.frame;
1188
- }
1189
- async next() {
1190
- if (this.previousScene) {
1191
- await this.previousScene.next();
1192
- if (this.currentScene.isFinished()) {
1193
- this.previousScene = null;
1194
- }
1195
- }
1196
- this.frame += this.speed;
1197
- if (this.currentScene.isFinished()) {
1198
- return true;
1199
- }
1200
- await this.currentScene.next();
1201
- if (this.previousScene && this.currentScene.isAfterTransitionIn()) {
1202
- this.previousScene = null;
1203
- }
1204
- if (this.currentScene.canTransitionOut()) {
1205
- this.previousScene = this.currentScene;
1206
- const nextScene = this.getNextScene(this.previousScene);
1207
- if (nextScene) {
1208
- this.previousScene.stopAllMedia();
1209
- this.currentScene = nextScene;
1210
- await this.currentScene.reset(this.previousScene);
1211
- }
1212
- if (!nextScene || this.currentScene.isAfterTransitionIn()) {
1213
- this.previousScene = null;
1214
- }
1215
- }
1216
- return this.currentScene.isFinished();
1217
- }
1218
- findBestScene(frame) {
1219
- let lastScene = this.scenes.current[0];
1220
- for (const scene of this.scenes.current) {
1221
- if (!scene.isCached() || scene.lastFrame > frame) {
1222
- return scene;
1223
- }
1224
- lastScene = scene;
1225
- }
1226
- return lastScene;
1227
- }
1228
- getNextScene(scene) {
1229
- const scenes = this.scenes.current;
1230
- if (!scene) {
1231
- return scenes[0];
1232
- }
1233
- const index = scenes.findIndex((s) => s === scene);
1234
- if (index < 0) {
1235
- return null;
1236
- }
1237
- return scenes[index + 1] ?? null;
1238
- }
1239
- }
1240
- class PlaybackStatus {
1241
- constructor(playback) {
1242
- this.playback = playback;
1243
- }
1244
- /**
1245
- * Convert seconds to frames using the current framerate.
1246
- *
1247
- * @param seconds - The seconds to convert.
1248
- */
1249
- secondsToFrames(seconds) {
1250
- return Math.ceil(seconds * this.playback.fps);
1251
- }
1252
- /**
1253
- * Convert frames to seconds using the current framerate.
1254
- *
1255
- * @param frames - The frames to convert.
1256
- */
1257
- framesToSeconds(frames) {
1258
- return frames / this.playback.fps;
1259
- }
1260
- get time() {
1261
- return this.framesToSeconds(this.playback.frame);
1262
- }
1263
- get frame() {
1264
- return this.playback.frame;
1265
- }
1266
- get speed() {
1267
- return this.playback.speed;
1268
- }
1269
- get fps() {
1270
- return this.playback.fps;
1271
- }
1272
- get state() {
1273
- return this.playback.state;
1274
- }
1275
- /**
1276
- * The time passed since the last frame in seconds.
1277
- */
1278
- get deltaTime() {
1279
- return this.framesToSeconds(1) * this.speed;
1280
- }
1281
- }
1282
- const SOURCE_URL_REGEX = /^\/\/# sourceURL=(.*)$/gm;
1283
- const INFO_LOG_REGEX = /ERROR: \d+:(\d+): (.*)/g;
1284
- const INFO_TOKEN_REGEX = /^'([^']+)'/;
1285
- const includeWithoutPreprocessor = `
1286
- The \`#include\` directive requires the use of a preprocessor.
1287
-
1288
- Make sure to import the shader from a file:
1289
-
1290
- \`\`\`ts
1291
- import shader from './shader.glsl';
1292
- \`\`\`
1293
-
1294
- Do **NOT** use the raw loader:
1295
-
1296
- \`\`\`ts
1297
- import shader from './shader.glsl?raw';
1298
- \`\`\`
1299
-
1300
- Do **NOT** use \`#include\` in an inline string:
1301
-
1302
- \`\`\`ts
1303
- const shader = \`\\
1304
- #include "example.glsl"
1305
- \`;
1306
- \`\`\`
1307
-
1308
- [Learn more](https://motioncanvas.io/docs/shaders) about working with shaders.
1309
- `;
1310
- class SharedWebGLContext {
1311
- constructor(logger) {
1312
- this.logger = logger;
1313
- this.gl = null;
1314
- this.currentOwner = null;
1315
- this.programLookup = /* @__PURE__ */ new Map();
1316
- }
1317
- borrow(owner) {
1318
- var _a;
1319
- if (this.currentOwner === owner) {
1320
- return this.gl;
1321
- }
1322
- (_a = this.currentOwner) == null ? void 0 : _a.teardown(this.gl);
1323
- this.currentOwner = owner;
1324
- this.currentOwner.setup(this.getGL());
1325
- return this.gl;
1326
- }
1327
- /**
1328
- * Dispose the WebGL context to free up resources.
1329
- */
1330
- dispose() {
1331
- var _a, _b;
1332
- if (!this.gl) {
1333
- return;
1334
- }
1335
- (_a = this.currentOwner) == null ? void 0 : _a.teardown(this.gl);
1336
- this.currentOwner = null;
1337
- this.gl.useProgram(null);
1338
- for (const { program, fragment, vertex } of this.programLookup.values()) {
1339
- this.gl.deleteProgram(program);
1340
- this.gl.deleteShader(fragment);
1341
- this.gl.deleteShader(vertex);
1342
- }
1343
- this.programLookup.clear();
1344
- (_b = this.gl.getExtension("WEBGL_lose_context")) == null ? void 0 : _b.loseContext();
1345
- this.gl.canvas.remove();
1346
- this.gl = null;
1347
- }
1348
- getProgram(fragment, vertex) {
1349
- const key = `${fragment}#${vertex}`;
1350
- if (this.programLookup.has(key)) {
1351
- return this.programLookup.get(key).program;
1352
- }
1353
- const gl = this.getGL();
1354
- const fragmentShader = this.getShader(gl.FRAGMENT_SHADER, fragment);
1355
- const vertexShader = this.getShader(gl.VERTEX_SHADER, vertex);
1356
- if (!fragmentShader || !vertexShader) {
1357
- return null;
1358
- }
1359
- const program = gl.createProgram();
1360
- gl.attachShader(program, fragmentShader);
1361
- gl.attachShader(program, vertexShader);
1362
- gl.linkProgram(program);
1363
- if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
1364
- this.logger.error({
1365
- message: "Failed to initialize the shader program.",
1366
- remarks: gl.getProgramInfoLog(program) ?? void 0,
1367
- stack: new Error().stack
1368
- });
1369
- gl.deleteProgram(program);
1370
- return null;
1371
- }
1372
- this.programLookup.set(key, {
1373
- program,
1374
- fragment: fragmentShader,
1375
- vertex: vertexShader
1376
- });
1377
- return program;
1378
- }
1379
- getShader(type, source) {
1380
- const gl = this.getGL();
1381
- const shader = gl.createShader(type);
1382
- gl.shaderSource(shader, source);
1383
- gl.compileShader(shader);
1384
- if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
1385
- const log = gl.getShaderInfoLog(shader);
1386
- logGlslError(this.logger, log, source);
1387
- gl.deleteShader(shader);
1388
- return null;
1389
- }
1390
- return shader;
1391
- }
1392
- getGL() {
1393
- if (this.gl) {
1394
- return this.gl;
1395
- }
1396
- this.gl = document.createElement("canvas").getContext("webgl2", {
1397
- depth: false,
1398
- premultipliedAlpha: false,
1399
- stencil: false,
1400
- powerPreference: "high-performance"
1401
- });
1402
- if (!this.gl) {
1403
- throw new Error("Failed to initialize WebGL.");
1404
- }
1405
- return this.gl;
1406
- }
1407
- }
1408
- function logGlslError(logger, log, source) {
1409
- let sourceUrl = null;
1410
- SOURCE_URL_REGEX.lastIndex = 0;
1411
- const sourceMatch = SOURCE_URL_REGEX.exec(source);
1412
- if (sourceMatch) {
1413
- const url = new URL(sourceMatch[1], window.location.origin);
1414
- url.searchParams.set("t", Date.now().toString());
1415
- sourceUrl = url.toString();
1416
- }
1417
- if (!log) {
1418
- logger.error({
1419
- message: `Unknown shader compilation error.`,
1420
- stack: fakeStackTrace(sourceUrl, 1, 0)
1421
- });
1422
- return null;
1423
- }
1424
- let logged = false;
1425
- let result;
1426
- while (result = INFO_LOG_REGEX.exec(log)) {
1427
- const [, line, message] = result;
1428
- let column = 0;
1429
- const match = message.match(INFO_TOKEN_REGEX);
1430
- if (match) {
1431
- const tokenLine = source.split("\n")[parseInt(line) - 1];
1432
- const index = tokenLine.indexOf(match[1]);
1433
- if (index !== -1) {
1434
- column = index;
1435
- }
1436
- if (match[1] === "include") {
1437
- const line2 = source.split("\n").find((line3) => line3.startsWith("#include"));
1438
- if (line2) {
1439
- logged = true;
1440
- logger.error({
1441
- message: `Shader compilation error: ${message}`,
1442
- remarks: includeWithoutPreprocessor
1443
- });
1444
- break;
1445
- }
1446
- }
1447
- }
1448
- logged = true;
1449
- logger.error({
1450
- message: `Shader compilation error: ${message}`,
1451
- stack: fakeStackTrace(sourceUrl, line, column)
1452
- });
1453
- }
1454
- if (!logged) {
1455
- logger.error({
1456
- message: `Shader compilation error: ${log}`,
1457
- stack: fakeStackTrace(sourceUrl, 1, 0)
1458
- });
1459
- }
1460
- }
1461
- function fakeStackTrace(file, line, column) {
1462
- if (!file) {
1463
- return void 0;
1464
- }
1465
- return navigator.userAgent.toLowerCase().includes("chrome") ? ` at (${file}:${line}:${column})` : `@${file}:${line}:${column}`;
1466
- }
1467
- class Player {
1468
- /**
1469
- * Triggered during each iteration of the update loop when the frame is ready
1470
- * to be rendered.
1471
- *
1472
- * @remarks
1473
- * Player does not perform any rendering on its own. For the animation to be
1474
- * visible, another class must subscribe to this event and perform the
1475
- * rendering itself. {@link Stage} can be used to display the animation.
1476
- *
1477
- * @eventProperty
1478
- */
1479
- get onRender() {
1480
- return this.render.subscribable;
1481
- }
1482
- get onStateChanged() {
1483
- return this.playerState.subscribable;
1484
- }
1485
- get onFrameChanged() {
1486
- return this.frame.subscribable;
1487
- }
1488
- get onDurationChanged() {
1489
- return this.duration.subscribable;
1490
- }
1491
- /**
1492
- * Triggered right after recalculation finishes.
1493
- *
1494
- * @remarks
1495
- * Can be used to provide visual feedback.
1496
- *
1497
- * @eventProperty
1498
- */
1499
- get onRecalculated() {
1500
- return this.recalculated.subscribable;
1501
- }
1502
- get startFrame() {
1503
- return Math.min(this.playback.duration, this.status.secondsToFrames(this.startTime));
1504
- }
1505
- get endFrame() {
1506
- return Math.min(this.playback.duration, this.status.secondsToFrames(this.endTime));
1507
- }
1508
- get finished() {
1509
- return this.playback.finished || this.playback.frame >= this.endFrame;
1510
- }
1511
- constructor(project, settings = {}, initialState = {}, initialFrame = -1) {
1512
- var _a, _b;
1513
- this.project = project;
1514
- this.settings = settings;
1515
- this.initialState = initialState;
1516
- this.initialFrame = initialFrame;
1517
- this.render = new AsyncEventDispatcher();
1518
- this.frame = new ValueDispatcher(0);
1519
- this.duration = new ValueDispatcher(0);
1520
- this.recalculated = new EventDispatcher();
1521
- this.lock = new Semaphore();
1522
- this.startTime = 0;
1523
- this.endTime = Infinity;
1524
- this.requestId = null;
1525
- this.renderTime = 0;
1526
- this.requestedSeek = -1;
1527
- this.requestedRender = false;
1528
- this.requestedRecalculation = true;
1529
- this.active = false;
1530
- this.playerState = new ValueDispatcher({
1531
- loop: true,
1532
- muted: true,
1533
- volume: 1,
1534
- speed: 1,
1535
- ...initialState,
1536
- paused: true
1537
- });
1538
- this.sharedWebGLContext = new SharedWebGLContext(this.project.logger);
1539
- this.requestedSeek = initialFrame;
1540
- this.logger = this.project.logger;
1541
- this.playback = new PlaybackManager();
1542
- this.status = new PlaybackStatus(this.playback);
1543
- this.size = settings.size ?? new Vector2(1920, 1080);
1544
- this.resolutionScale = settings.resolutionScale ?? 1;
1545
- this.startTime = ((_a = settings.range) == null ? void 0 : _a[0]) ?? 0;
1546
- this.endTime = ((_b = settings.range) == null ? void 0 : _b[1]) ?? Infinity;
1547
- this.playback.fps = settings.fps ?? 60;
1548
- const scenes = [];
1549
- for (const description of project.scenes) {
1550
- const scene = new description.klass({
1551
- ...description,
1552
- playback: this.status,
1553
- logger: this.project.logger,
1554
- size: this.size,
1555
- resolutionScale: this.resolutionScale,
1556
- sharedWebGLContext: this.sharedWebGLContext,
1557
- experimentalFeatures: project.experimentalFeatures
1558
- });
1559
- scene.onReloaded.subscribe(() => this.requestRecalculation());
1560
- scene.variables.updateSignals(project.variables ?? {});
1561
- scenes.push(scene);
1562
- }
1563
- this.playback.setup(scenes);
1564
- this.activate();
1565
- }
1566
- async configure(settings) {
1567
- await this.lock.acquire();
1568
- let frame = this.playback.frame;
1569
- let recalculate = false;
1570
- this.startTime = settings.range[0];
1571
- this.endTime = settings.range[1];
1572
- const newFps = Math.max(1, settings.fps);
1573
- if (this.playback.fps !== newFps) {
1574
- const ratio = newFps / this.playback.fps;
1575
- this.playback.fps = newFps;
1576
- frame = Math.floor(frame * ratio);
1577
- recalculate = true;
1578
- }
1579
- if (!settings.size.exactlyEquals(this.size) || settings.resolutionScale !== this.resolutionScale) {
1580
- this.size = settings.size;
1581
- this.resolutionScale = settings.resolutionScale;
1582
- this.playback.reload({
1583
- size: this.size,
1584
- resolutionScale: this.resolutionScale
1585
- });
1586
- }
1587
- this.lock.release();
1588
- if (recalculate) {
1589
- this.playback.reload();
1590
- this.frame.current = frame;
1591
- this.requestRecalculation();
1592
- this.requestedSeek = frame;
1593
- }
1594
- }
1595
- /**
1596
- * Whether the given frame is inside the animation range.
1597
- *
1598
- * @param frame - The frame to check.
1599
- */
1600
- isInRange(frame) {
1601
- return frame >= 0 && frame <= this.playback.duration;
1602
- }
1603
- /**
1604
- * Whether the given frame is inside the user-defined range.
1605
- *
1606
- * @param frame - The frame to check.
1607
- */
1608
- isInUserRange(frame) {
1609
- return frame >= this.startFrame && frame <= this.endFrame;
1610
- }
1611
- requestSeek(value) {
1612
- this.requestedSeek = this.clampRange(value);
1613
- }
1614
- requestPreviousFrame() {
1615
- this.requestedSeek = this.frame.current - this.playback.speed;
1616
- }
1617
- requestNextFrame() {
1618
- this.requestedSeek = this.frame.current + this.playback.speed;
1619
- }
1620
- requestReset() {
1621
- this.requestedSeek = 0;
1622
- }
1623
- requestRender() {
1624
- this.requestedRender = true;
1625
- }
1626
- toggleLoop(value = !this.playerState.current.loop) {
1627
- if (value !== this.playerState.current.loop) {
1628
- this.playerState.current = {
1629
- ...this.playerState.current,
1630
- loop: value
1631
- };
1632
- }
1633
- }
1634
- togglePlayback(value = this.playerState.current.paused) {
1635
- if (value === this.playerState.current.paused) {
1636
- this.playerState.current = {
1637
- ...this.playerState.current,
1638
- paused: !value
1639
- };
1640
- if (value && !this.playerState.current.loop && this.playback.frame === this.playback.duration) {
1641
- this.requestReset();
1642
- }
1643
- }
1644
- }
1645
- toggleAudio(value = this.playerState.current.muted) {
1646
- if (value === this.playerState.current.muted) {
1647
- this.playerState.current = {
1648
- ...this.playerState.current,
1649
- muted: !value
1650
- };
1651
- }
1652
- }
1653
- setAudioVolume(value) {
1654
- const clampedValue = clamp(0, 1, value);
1655
- if (clampedValue !== this.playerState.current.volume) {
1656
- this.playerState.current = {
1657
- ...this.playerState.current,
1658
- volume: clampedValue
1659
- };
1660
- }
1661
- }
1662
- addAudioVolume(value) {
1663
- this.setAudioVolume(this.playerState.current.volume + value);
1664
- }
1665
- setSpeed(value) {
1666
- if (value !== this.playerState.current.speed) {
1667
- this.playback.speed = value;
1668
- this.playback.reload();
1669
- this.playerState.current = {
1670
- ...this.playerState.current,
1671
- speed: value
1672
- };
1673
- this.requestRecalculation();
1674
- }
1675
- }
1676
- setVariables(variables) {
1677
- for (const scene of this.playback.onScenesRecalculated.current) {
1678
- scene.variables.updateSignals(variables);
1679
- }
1680
- }
1681
- /**
1682
- * Activate the player.
1683
- *
1684
- * @remarks
1685
- * A player needs to be active in order for the update loop to run. Each
1686
- * player is active by default.
1687
- */
1688
- activate() {
1689
- this.active = true;
1690
- this.request();
1691
- }
1692
- /**
1693
- * Deactivate the player.
1694
- *
1695
- * @remarks
1696
- * Deactivating the player prevents its update loop from running. This should
1697
- * be done before disposing the player, to prevent it from running in the
1698
- * background.
1699
- *
1700
- * Just pausing the player does not stop the loop.
1701
- */
1702
- deactivate() {
1703
- this.active = false;
1704
- this.sharedWebGLContext.dispose();
1705
- this.playback.currentScene.stopAllMedia();
1706
- if (this.requestId !== null) {
1707
- cancelAnimationFrame(this.requestId);
1708
- this.requestId = null;
1709
- }
1710
- }
1711
- requestRecalculation() {
1712
- this.requestedRecalculation = true;
1713
- this.request();
1714
- }
1715
- async prepare() {
1716
- const state = {
1717
- ...this.playerState.current,
1718
- seek: this.requestedSeek,
1719
- render: this.requestedRender
1720
- };
1721
- this.requestedSeek = -1;
1722
- this.requestedRender = false;
1723
- if (this.requestedRecalculation) {
1724
- if (state.seek < 0) {
1725
- state.seek = this.playback.frame;
1726
- }
1727
- try {
1728
- await this.playback.recalculate();
1729
- this.duration.current = this.playback.frame;
1730
- this.recalculated.dispatch();
1731
- } catch (e) {
1732
- this.requestSeek(state.seek);
1733
- throw e;
1734
- } finally {
1735
- this.requestedRecalculation = false;
1736
- }
1737
- }
1738
- if (!state.loop && this.finished && !state.paused && state.seek < 0 || this.endFrame === this.startFrame) {
1739
- this.togglePlayback(false);
1740
- state.paused = true;
1741
- state.seek = this.endFrame === this.startFrame ? state.seek : this.startFrame;
1742
- }
1743
- if (state.loop && (state.seek > this.endFrame || this.finished && !state.paused) && this.startFrame !== this.endTime) {
1744
- state.seek = this.startFrame;
1745
- }
1746
- return state;
1747
- }
1748
- async run() {
1749
- const state = await this.prepare();
1750
- const previousState = this.playback.state;
1751
- this.playback.state = state.paused ? PlaybackState.Paused : PlaybackState.Playing;
1752
- if (state.seek >= 0 || !this.isInUserRange(this.status.frame)) {
1753
- const seekFrame = state.seek < 0 ? this.status.frame : state.seek;
1754
- const clampedFrame = this.clampRange(seekFrame);
1755
- this.logger.profile("seek time");
1756
- await this.playback.seek(clampedFrame);
1757
- this.logger.profile("seek time");
1758
- } else if (state.paused) {
1759
- if (state.render || state.paused && previousState !== PlaybackState.Paused) {
1760
- await this.render.dispatch();
1761
- }
1762
- this.request();
1763
- return;
1764
- } else if (this.status.frame < this.endFrame) {
1765
- await this.playback.progress();
1766
- }
1767
- if (!state.paused && this.playback.currentScene.slides.isWaiting()) {
1768
- this.togglePlayback(false);
1769
- state.paused = true;
1770
- }
1771
- await this.render.dispatch();
1772
- this.frame.current = this.playback.frame;
1773
- this.request();
1774
- }
1775
- request() {
1776
- if (!this.active)
1777
- return;
1778
- this.requestId ?? (this.requestId = requestAnimationFrame(async (time) => {
1779
- this.requestId = null;
1780
- if (time - this.renderTime >= 1e3 / (this.status.fps + 5)) {
1781
- this.renderTime = time;
1782
- await this.lock.acquire();
1783
- try {
1784
- await this.run();
1785
- } catch (e) {
1786
- this.logger.error(e);
1787
- }
1788
- this.lock.release();
1789
- } else {
1790
- this.request();
1791
- }
1792
- }));
1793
- }
1794
- clampRange(frame) {
1795
- return clamp(this.startFrame, this.endFrame, frame);
1796
- }
1797
- }
1798
- function getFullPreviewSettings(project) {
1799
- return {
1800
- ...project.settings.shared,
1801
- ...project.settings.preview
1802
- };
1803
- }
1804
- class Stage {
1805
- get canvasSize() {
1806
- return this.size.scale(this.resolutionScale);
1807
- }
1808
- constructor() {
1809
- this.background = null;
1810
- this.resolutionScale = 1;
1811
- this.colorSpace = "srgb";
1812
- this.size = Vector2.zero;
1813
- this.finalBuffer = document.createElement("canvas");
1814
- this.currentBuffer = document.createElement("canvas");
1815
- this.previousBuffer = document.createElement("canvas");
1816
- const colorSpace = this.colorSpace;
1817
- this.context = getContext({ colorSpace }, this.finalBuffer);
1818
- this.currentContext = getContext({ colorSpace }, this.currentBuffer);
1819
- this.previousContext = getContext({ colorSpace }, this.previousBuffer);
1820
- }
1821
- configure({ colorSpace = this.colorSpace, size = this.size, resolutionScale = this.resolutionScale, background = this.background }) {
1822
- if (colorSpace !== this.colorSpace) {
1823
- this.colorSpace = colorSpace;
1824
- this.context = getContext({ colorSpace }, this.finalBuffer);
1825
- this.currentContext = getContext({ colorSpace }, this.currentBuffer);
1826
- this.previousContext = getContext({ colorSpace }, this.previousBuffer);
1827
- }
1828
- if (!size.exactlyEquals(this.size) || resolutionScale !== this.resolutionScale) {
1829
- this.resolutionScale = resolutionScale;
1830
- this.size = size;
1831
- this.resizeCanvas(this.context);
1832
- this.resizeCanvas(this.currentContext);
1833
- this.resizeCanvas(this.previousContext);
1834
- }
1835
- this.background = typeof background === "string" ? background : (background == null ? void 0 : background.serialize()) ?? null;
1836
- }
1837
- async render(currentScene, previousScene) {
1838
- const previousOnTop = previousScene ? unwrap(currentScene.previousOnTop) : false;
1839
- if (previousScene) {
1840
- await previousScene.render(this.previousContext);
1841
- }
1842
- await currentScene.render(this.currentContext);
1843
- const size = this.canvasSize;
1844
- this.context.clearRect(0, 0, size.width, size.height);
1845
- if (this.background) {
1846
- this.context.save();
1847
- this.context.fillStyle = this.background;
1848
- this.context.fillRect(0, 0, size.width, size.height);
1849
- this.context.restore();
1850
- }
1851
- if (previousScene && !previousOnTop) {
1852
- this.context.drawImage(this.previousBuffer, 0, 0);
1853
- }
1854
- this.context.drawImage(this.currentBuffer, 0, 0);
1855
- if (previousOnTop) {
1856
- this.context.drawImage(this.previousBuffer, 0, 0);
1857
- }
1858
- }
1859
- resizeCanvas(context) {
1860
- const size = this.canvasSize;
1861
- context.canvas.width = size.width;
1862
- context.canvas.height = size.height;
1863
- }
1864
- }
1865
- const stylesNew = `
1866
- .overlay {
1867
- position: absolute;
1868
- left: 0;
1869
- right: 0;
1870
- top: 0;
1871
- bottom: 0;
1872
- display: flex;
1873
- align-items: center;
1874
- justify-content: center;
1875
- opacity: 0;
1876
- transition: opacity 0.1s;
1877
- z-index: 0;
1878
- }
1879
- .canvas {
1880
- width: 100%;
1881
- display: block;
1882
- opacity: 1;
1883
- transition: opacity 0.1s;
1884
- }
1885
- `;
1886
- const TEMPLATE = `<style>${stylesNew}</style><div class="overlay"></div>`;
1887
- const ID = "twick-player";
1888
- var State;
1889
- (function(State2) {
1890
- State2["Initial"] = "initial";
1891
- State2["Loading"] = "loading";
1892
- State2["Ready"] = "ready";
1893
- State2["Error"] = "error";
1894
- })(State || (State = {}));
1895
- class TwickPlayer extends HTMLElement {
1896
- constructor() {
1897
- super();
1898
- __publicField(this, "root");
1899
- __publicField(this, "canvas");
1900
- __publicField(this, "overlay");
1901
- __publicField(this, "state", State.Initial);
1902
- __publicField(this, "project", null);
1903
- __publicField(this, "player", null);
1904
- __publicField(this, "defaultSettings");
1905
- __publicField(this, "abortController", null);
1906
- __publicField(this, "playing", false);
1907
- __publicField(this, "stage", new Stage());
1908
- __publicField(this, "time", 0);
1909
- __publicField(this, "duration", 0);
1910
- // in frames
1911
- __publicField(this, "looping", true);
1912
- __publicField(this, "volume", 1);
1913
- __publicField(this, "volumeChangeRequested", true);
1914
- /**
1915
- * Triggered by the timeline.
1916
- */
1917
- __publicField(this, "handleSeekTo", (event) => {
1918
- var _a;
1919
- if (!this.project) {
1920
- return;
1921
- }
1922
- const e = event;
1923
- this.time = e.detail;
1924
- (_a = this.player) == null ? void 0 : _a.requestSeek(e.detail * this.player.playback.fps);
1925
- this.volumeChangeRequested = true;
1926
- });
1927
- __publicField(this, "handleVolumeChange", (event) => {
1928
- var _a;
1929
- if (!this.project) {
1930
- return;
1931
- }
1932
- const e = event;
1933
- this.volume = e.detail;
1934
- (_a = this.player) == null ? void 0 : _a.playback.currentScene.adjustVolume(this.volume);
1935
- });
1936
- /**
1937
- * Triggered by the player.
1938
- */
1939
- __publicField(this, "handleFrameChanged", (frame) => {
1940
- var _a;
1941
- if (!this.project || !this.player) {
1942
- return;
1943
- }
1944
- this.time = frame / this.player.playback.fps;
1945
- if (this.volumeChangeRequested || frame === 0) {
1946
- (_a = this.player) == null ? void 0 : _a.playback.currentScene.adjustVolume(this.volume);
1947
- this.volumeChangeRequested = false;
1948
- }
1949
- });
1950
- /**
1951
- * Called on every frame.
1952
- */
1953
- __publicField(this, "render", async () => {
1954
- if (this.player && this.project) {
1955
- await this.stage.render(this.player.playback.currentScene, this.player.playback.previousScene);
1956
- this.dispatchEvent(new CustomEvent("timeupdate", { detail: this.time }));
1957
- const durationInFrames = this.player.playback.duration;
1958
- if (durationInFrames === this.duration) {
1959
- return;
1960
- }
1961
- this.duration = durationInFrames;
1962
- const durationInSeconds = durationInFrames / this.player.playback.fps;
1963
- this.dispatchEvent(new CustomEvent("duration", { detail: durationInSeconds }));
1964
- }
1965
- });
1966
- this.root = this.attachShadow({ mode: "open" });
1967
- this.root.innerHTML = TEMPLATE;
1968
- this.overlay = this.root.querySelector(".overlay");
1969
- this.canvas = this.stage.finalBuffer;
1970
- this.canvas.classList.add("canvas");
1971
- this.root.prepend(this.canvas);
1972
- this.setState(State.Initial);
1973
- }
1974
- static get observedAttributes() {
1975
- return [
1976
- "playing",
1977
- "variables",
1978
- "looping",
1979
- "fps",
1980
- "quality",
1981
- "width",
1982
- "height",
1983
- "volume"
1984
- ];
1985
- }
1986
- get fps() {
1987
- var _a;
1988
- const attr = this.getAttribute("fps");
1989
- return attr ? parseFloat(attr) : ((_a = this.defaultSettings) == null ? void 0 : _a.fps) ?? 60;
1990
- }
1991
- get quality() {
1992
- var _a;
1993
- const attr = this.getAttribute("quality");
1994
- return attr ? parseFloat(attr) : ((_a = this.defaultSettings) == null ? void 0 : _a.resolutionScale) ?? 1;
1995
- }
1996
- get width() {
1997
- var _a;
1998
- const attr = this.getAttribute("width");
1999
- return attr ? parseFloat(attr) : ((_a = this.defaultSettings) == null ? void 0 : _a.size.width) ?? 0;
2000
- }
2001
- get height() {
2002
- var _a;
2003
- const attr = this.getAttribute("height");
2004
- return attr ? parseFloat(attr) : ((_a = this.defaultSettings) == null ? void 0 : _a.size.height) ?? 0;
2005
- }
2006
- get variables() {
2007
- var _a;
2008
- try {
2009
- const attr = this.getAttribute("variables");
2010
- return attr ? JSON.parse(attr) : {};
2011
- } catch {
2012
- (_a = this.project) == null ? void 0 : _a.logger.warn(`Project variables could not be parsed.`);
2013
- return {};
2014
- }
2015
- }
2016
- setProject(project) {
2017
- this.updateProject(project);
2018
- }
2019
- setState(state) {
2020
- this.state = state;
2021
- this.setPlaying(this.playing);
2022
- }
2023
- setPlaying(value) {
2024
- var _a, _b;
2025
- if (this.state === State.Ready && value) {
2026
- (_a = this.player) == null ? void 0 : _a.togglePlayback(true);
2027
- this.playing = true;
2028
- } else {
2029
- (_b = this.player) == null ? void 0 : _b.togglePlayback(false);
2030
- this.playing = false;
2031
- }
2032
- }
2033
- async updateProject(project) {
2034
- var _a, _b, _c, _d, _e;
2035
- const playing = this.playing;
2036
- this.setState(State.Initial);
2037
- (_a = this.abortController) == null ? void 0 : _a.abort();
2038
- this.abortController = new AbortController();
2039
- this.project = project;
2040
- console.log(project);
2041
- this.defaultSettings = getFullPreviewSettings(this.project);
2042
- const player = new Player(this.project);
2043
- player.setVariables(this.variables);
2044
- player.toggleLoop(this.looping);
2045
- (_b = this.player) == null ? void 0 : _b.onRender.unsubscribe(this.render);
2046
- (_c = this.player) == null ? void 0 : _c.onFrameChanged.unsubscribe(this.handleFrameChanged);
2047
- (_d = this.player) == null ? void 0 : _d.togglePlayback(false);
2048
- (_e = this.player) == null ? void 0 : _e.deactivate();
2049
- this.player = player;
2050
- this.updateSettings();
2051
- this.setState(State.Ready);
2052
- this.dispatchEvent(new CustomEvent("playerready", { detail: this.player }));
2053
- this.setPlaying(playing);
2054
- this.player.onRender.subscribe(this.render);
2055
- this.player.onFrameChanged.subscribe(this.handleFrameChanged);
2056
- }
2057
- attributeChangedCallback(name, _, newValue) {
2058
- var _a, _b, _c, _d;
2059
- switch (name) {
2060
- case "playing":
2061
- this.setPlaying(newValue === "true");
2062
- break;
2063
- case "variables":
2064
- (_a = this.player) == null ? void 0 : _a.setVariables(this.variables);
2065
- (_b = this.player) == null ? void 0 : _b.requestSeek(this.player.playback.frame);
2066
- (_c = this.player) == null ? void 0 : _c.playback.reload();
2067
- break;
2068
- case "looping":
2069
- this.looping = newValue === "true";
2070
- (_d = this.player) == null ? void 0 : _d.toggleLoop(newValue === "true");
2071
- break;
2072
- case "fps":
2073
- case "quality":
2074
- case "width":
2075
- case "height":
2076
- this.updateSettings();
2077
- break;
2078
- case "volume":
2079
- this.volume = newValue;
2080
- this.volumeChangeRequested = true;
2081
- }
2082
- }
2083
- /**
2084
- * Runs when the element is removed from the DOM.
2085
- */
2086
- disconnectedCallback() {
2087
- var _a, _b;
2088
- (_a = this.player) == null ? void 0 : _a.deactivate();
2089
- (_b = this.player) == null ? void 0 : _b.onRender.unsubscribe(this.render);
2090
- this.removeEventListener("seekto", this.handleSeekTo);
2091
- this.removeEventListener("volumechange", this.handleVolumeChange);
2092
- }
2093
- /**
2094
- * Runs when the element is added to the DOM.
2095
- */
2096
- connectedCallback() {
2097
- var _a, _b;
2098
- (_a = this.player) == null ? void 0 : _a.activate();
2099
- (_b = this.player) == null ? void 0 : _b.onRender.subscribe(this.render);
2100
- this.addEventListener("seekto", this.handleSeekTo);
2101
- this.addEventListener("volumechange", this.handleVolumeChange);
2102
- }
2103
- updateSettings() {
2104
- var _a;
2105
- if (!this.defaultSettings) {
2106
- return;
2107
- }
2108
- const settings = {
2109
- ...this.defaultSettings,
2110
- size: new Vector2(this.width, this.height),
2111
- resolutionScale: this.quality,
2112
- fps: this.fps
2113
- };
2114
- this.stage.configure(settings);
2115
- (_a = this.player) == null ? void 0 : _a.configure(settings);
2116
- }
2117
- }
2118
- if (!customElements.get(ID)) {
2119
- customElements.define(ID, TwickPlayer);
2120
- }
2121
- //# sourceMappingURL=internal-pPYo5Irb.cjs.map