@twick/2d 0.15.17 → 0.15.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +62 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -7
- package/dist/index.d.ts +21 -7
- package/dist/index.js +62 -26
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -5502,6 +5502,8 @@ var Media = class extends Rect {
|
|
|
5502
5502
|
super(props);
|
|
5503
5503
|
this.lastTime = -1;
|
|
5504
5504
|
this.isSchedulingPlay = false;
|
|
5505
|
+
/** Used with clipStart for sync (trim offset in source). */
|
|
5506
|
+
this.trimStart = 0;
|
|
5505
5507
|
if (!this.awaitCanPlay()) {
|
|
5506
5508
|
setTimeout(() => this.scheduleSeek(this.time()), 0);
|
|
5507
5509
|
}
|
|
@@ -5509,6 +5511,8 @@ var Media = class extends Rect {
|
|
|
5509
5511
|
this.play();
|
|
5510
5512
|
}
|
|
5511
5513
|
this.volume = props.volume ?? 1;
|
|
5514
|
+
this.clipStart = props.clipStart;
|
|
5515
|
+
this.trimStart = props.trimStart ?? 0;
|
|
5512
5516
|
if (!this.awaitCanPlay()) {
|
|
5513
5517
|
this.setVolume(this.volume);
|
|
5514
5518
|
}
|
|
@@ -5550,14 +5554,27 @@ var Media = class extends Rect {
|
|
|
5550
5554
|
}
|
|
5551
5555
|
/**
|
|
5552
5556
|
* Sync the underlying media element to the given time (e.g. draw/playback time).
|
|
5553
|
-
* When `time` is passed (e.g. from Scene2D.draw), that
|
|
5554
|
-
* does not depend on the node's time signal
|
|
5557
|
+
* Used for both Video and Audio. When `time` is passed (e.g. from Scene2D.draw), that
|
|
5558
|
+
* value is used so sync does not depend on the node's time signal.
|
|
5559
|
+
* If this node has clipStart set, global time is converted to clip-relative time:
|
|
5560
|
+
* syncTime = trimStart + (time - clipStart) * playbackRate.
|
|
5555
5561
|
* When omitted, falls back to this.time().
|
|
5556
|
-
*
|
|
5562
|
+
* When waitForSeek is true, returns a promise that resolves when the seek completes so
|
|
5563
|
+
* the draw can wait and show the correct frame/sample when paused.
|
|
5557
5564
|
*/
|
|
5558
|
-
syncToCurrentTime(time) {
|
|
5559
|
-
|
|
5560
|
-
this.
|
|
5565
|
+
syncToCurrentTime(time, options) {
|
|
5566
|
+
let syncTime;
|
|
5567
|
+
if (time !== void 0 && this.clipStart !== void 0) {
|
|
5568
|
+
syncTime = this.trimStart + (time - this.clipStart) * this.playbackRate();
|
|
5569
|
+
} else {
|
|
5570
|
+
syncTime = time ?? this.time();
|
|
5571
|
+
}
|
|
5572
|
+
const promise = this.setCurrentTime(syncTime, {
|
|
5573
|
+
skipCollectPromise: options?.waitForSeek ?? true
|
|
5574
|
+
});
|
|
5575
|
+
if (options?.waitForSeek) {
|
|
5576
|
+
return promise;
|
|
5577
|
+
}
|
|
5561
5578
|
}
|
|
5562
5579
|
setCurrentTime(value, options) {
|
|
5563
5580
|
try {
|
|
@@ -5566,30 +5583,41 @@ var Media = class extends Rect {
|
|
|
5566
5583
|
if (media.readyState < 2) {
|
|
5567
5584
|
this.lastTime = value;
|
|
5568
5585
|
this.time(value);
|
|
5569
|
-
|
|
5570
|
-
media
|
|
5571
|
-
|
|
5572
|
-
|
|
5586
|
+
return new Promise((resolve) => {
|
|
5587
|
+
this.waitForCanPlay(media, () => {
|
|
5588
|
+
media.currentTime = value;
|
|
5589
|
+
this.lastTime = value;
|
|
5590
|
+
this.time(value);
|
|
5591
|
+
const onSeeked = () => {
|
|
5592
|
+
media.removeEventListener("seeked", onSeeked);
|
|
5593
|
+
resolve();
|
|
5594
|
+
};
|
|
5595
|
+
if (media.seeking) {
|
|
5596
|
+
media.addEventListener("seeked", onSeeked);
|
|
5597
|
+
} else {
|
|
5598
|
+
resolve();
|
|
5599
|
+
}
|
|
5600
|
+
});
|
|
5573
5601
|
});
|
|
5574
|
-
return;
|
|
5575
5602
|
}
|
|
5576
5603
|
media.currentTime = value;
|
|
5577
5604
|
this.lastTime = value;
|
|
5578
5605
|
this.time(value);
|
|
5606
|
+
const seekPromise = media.seeking ? new Promise((resolve) => {
|
|
5607
|
+
const listener = () => {
|
|
5608
|
+
resolve();
|
|
5609
|
+
media.removeEventListener("seeked", listener);
|
|
5610
|
+
};
|
|
5611
|
+
media.addEventListener("seeked", listener);
|
|
5612
|
+
}) : Promise.resolve();
|
|
5579
5613
|
if (media.seeking && !options?.skipCollectPromise) {
|
|
5580
|
-
import_core32.DependencyContext.collectPromise(
|
|
5581
|
-
new Promise((resolve) => {
|
|
5582
|
-
const listener = () => {
|
|
5583
|
-
resolve();
|
|
5584
|
-
media.removeEventListener("seeked", listener);
|
|
5585
|
-
};
|
|
5586
|
-
media.addEventListener("seeked", listener);
|
|
5587
|
-
})
|
|
5588
|
-
);
|
|
5614
|
+
import_core32.DependencyContext.collectPromise(seekPromise);
|
|
5589
5615
|
}
|
|
5616
|
+
return seekPromise;
|
|
5590
5617
|
} catch (error) {
|
|
5591
5618
|
this.lastTime = value;
|
|
5592
5619
|
this.time(value);
|
|
5620
|
+
return Promise.resolve();
|
|
5593
5621
|
}
|
|
5594
5622
|
}
|
|
5595
5623
|
setVolume(volume) {
|
|
@@ -10729,7 +10757,7 @@ var Scene2D = class extends import_core60.GeneratorScene {
|
|
|
10729
10757
|
this.renderLifecycle.dispatch([import_core60.SceneRenderEvent.BeginRender, context]);
|
|
10730
10758
|
this.getView().playbackState(this.playback.state).globalTime(this.playback.time).fps(this.playback.fps);
|
|
10731
10759
|
if (this.playback.state === import_core60.PlaybackState.Paused) {
|
|
10732
|
-
this.syncAllMediaToCurrentTime();
|
|
10760
|
+
await this.syncAllMediaToCurrentTime(true);
|
|
10733
10761
|
}
|
|
10734
10762
|
await this.getView().render(context);
|
|
10735
10763
|
this.renderLifecycle.dispatch([import_core60.SceneRenderEvent.FinishRender, context]);
|
|
@@ -10862,23 +10890,31 @@ var Scene2D = class extends import_core60.GeneratorScene {
|
|
|
10862
10890
|
return returnObjects;
|
|
10863
10891
|
}
|
|
10864
10892
|
/**
|
|
10865
|
-
* Seek all registered Media nodes to the current playback time.
|
|
10866
|
-
* Passes draw time
|
|
10893
|
+
* Seek all registered Media nodes (Video and Audio) to the current playback time.
|
|
10894
|
+
* Passes draw time; nodes with clipStart convert it to clip-relative time.
|
|
10895
|
+
* When waitForSeek is true, waits for each media seek to complete so the next draw shows the correct frame/sample.
|
|
10867
10896
|
*/
|
|
10868
|
-
syncAllMediaToCurrentTime() {
|
|
10897
|
+
async syncAllMediaToCurrentTime(waitForSeek) {
|
|
10869
10898
|
const drawTime = this.playback.time;
|
|
10870
10899
|
const mediaNodes = Array.from(this.registeredNodes.values()).filter(
|
|
10871
10900
|
(node) => node instanceof Media
|
|
10872
10901
|
);
|
|
10873
|
-
|
|
10902
|
+
const results = mediaNodes.map((media) => {
|
|
10874
10903
|
try {
|
|
10875
|
-
media.syncToCurrentTime(drawTime);
|
|
10904
|
+
return media.syncToCurrentTime(drawTime, { waitForSeek });
|
|
10876
10905
|
} catch (e) {
|
|
10877
10906
|
this.logger.warn({
|
|
10878
10907
|
message: `syncAllMediaToCurrentTime: skipped node ${media.key ?? "unknown"}`,
|
|
10879
10908
|
object: e
|
|
10880
10909
|
});
|
|
10910
|
+
return void 0;
|
|
10881
10911
|
}
|
|
10912
|
+
});
|
|
10913
|
+
if (waitForSeek) {
|
|
10914
|
+
const promises = results.filter(
|
|
10915
|
+
(p) => p !== void 0
|
|
10916
|
+
);
|
|
10917
|
+
await Promise.all(promises);
|
|
10882
10918
|
}
|
|
10883
10919
|
}
|
|
10884
10920
|
stopAllMedia() {
|