Ping-pong turns on the last key, and stepped rows hold the key they last passed (#112)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f68941fa3a
commit
cc14988338
7 files changed
+72
-22
No files matched your search
@@ -33,7 +33,10 @@ export class AnimationEditor extends AssetTabEditor<AnimationAsset, TimelineCanv
|
||||
this.playButton = new Button('Play', { width: 64, onClick: () => this.togglePlay() });
|
||||
this.centreButton = new Button('Centre', { onClick: () => this.preview.fit() });
|
||||
const timeline = new TimelineCanvas(state);
|
||||
this.preview = new PreviewCanvas(state, () => timeline.playhead);
|
||||
this.preview = new PreviewCanvas(state, () => ({
|
||||
frame: timeline.playhead,
|
||||
reverse: timeline.playheadReverse,
|
||||
}));
|
||||
timeline.onPlayhead = () => this.preview.redraw();
|
||||
this.mount(timeline, [this.rootPicker, this.addRowButton, this.playButton, this.centreButton]);
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ export class PreviewCanvas extends WorldViewport {
|
||||
|
||||
constructor(
|
||||
state: EditorState,
|
||||
/** Where the timeline's playhead stands, in frames. */
|
||||
private readonly playhead: () => number,
|
||||
/** Where the timeline's playhead stands, in frames, and whether it runs ping-pong's way back. */
|
||||
private readonly playhead: () => { frame: number; reverse: boolean },
|
||||
) {
|
||||
super(state);
|
||||
this.on('pointerdown', (e: FederatedPointerEvent) => this.onPointerDown(e));
|
||||
@@ -95,7 +95,8 @@ export class PreviewCanvas extends WorldViewport {
|
||||
|
||||
protected override collectFrame(): Frame {
|
||||
const asset = this.assetId ? findAssetOf(this.state.project, this.assetId, 'animation') : undefined;
|
||||
const holder = asset && previewHolder(this.state.project, asset, this.playhead());
|
||||
const head = this.playhead();
|
||||
const holder = asset && previewHolder(this.state.project, asset, head.frame, head.reverse);
|
||||
return collectHolderItems(this.state.project, holder, Theme.colors.viewport);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,8 @@ export class TimelineCanvas extends Widget {
|
||||
private assetId = '';
|
||||
/** Where the playhead stands, in frames – fractional while playing. */
|
||||
playhead = 0;
|
||||
/** Whether the playhead runs ping-pong's way back – a jumping value then holds the key above. */
|
||||
playheadReverse = false;
|
||||
/** Seconds since play began; the playhead is a function of it (see `animationPlayheadAt`). */
|
||||
private time = 0;
|
||||
private playingNow = false;
|
||||
@@ -160,6 +162,7 @@ export class TimelineCanvas extends Widget {
|
||||
stop(): void {
|
||||
this.playingNow = false;
|
||||
this.playhead = 0;
|
||||
this.playheadReverse = false;
|
||||
this.time = 0;
|
||||
this.onPlayhead();
|
||||
}
|
||||
@@ -171,6 +174,7 @@ export class TimelineCanvas extends Widget {
|
||||
this.time += dt;
|
||||
const at = animationPlayheadAt(asset, this.time);
|
||||
this.playhead = at.frame;
|
||||
this.playheadReverse = at.reverse;
|
||||
if (at.finished) this.playingNow = false;
|
||||
this.redraw();
|
||||
this.onPlayhead();
|
||||
@@ -179,6 +183,7 @@ export class TimelineCanvas extends Widget {
|
||||
/** Puts the playhead on a frame – what the ruler does, and what a check does without a pointer. */
|
||||
scrub(frame: number): void {
|
||||
this.playhead = Math.max(0, frame);
|
||||
this.playheadReverse = false;
|
||||
const asset = this.asset();
|
||||
if (asset) this.time = this.timeOf(asset, this.playhead);
|
||||
this.redraw();
|
||||
|
||||
Reference in new issue
Block a user