blob: 0ee04dcbac50bbda671aa7f0e15c70615620ec36 [file] [log] [blame]
/**
* @module modules/uniform-time-sk
* @description <h2><code>uniform-time-sk</code></h2>
*
* Constructs a handler for the iTime uniform.
*
* Displays the play/pause and rewind buttons.
*/
import { define } from 'elements-sk/define';
import { html } from 'lit-html';
import { ElementSk } from '../ElementSk';
import 'elements-sk/icon/play-arrow-icon-sk';
import 'elements-sk/icon/pause-icon-sk';
import 'elements-sk/icon/fast-rewind-icon-sk';
import { Uniform, UniformControl } from '../uniform/uniform';
import 'elements-sk/styles/buttons';
const defaultUniform: Uniform = {
name: 'iTime',
rows: 1,
columns: 1,
slot: 0,
};
// The type of Date.now.
type DateNow = ()=> number;
export class UniformTimeSk extends ElementSk implements UniformControl {
private startTime: number = 0; // The time as recorded from this._dateNow in ms.
private pauseTime: number = 0; // The time we were at when pause was pressed, in seconds.
private _uniform: Uniform = defaultUniform;
private _dateNow: DateNow = Date.now; // A replaceable Date.now() function for testing.
private playing: boolean = true;
constructor() {
super(UniformTimeSk.template);
}
private static template = (ele: UniformTimeSk) => html`
<button id="restart" @click=${ele.restart}>
<fast-rewind-icon-sk></fast-rewind-icon-sk>
</button>
<button id="playpause" @click=${ele.togglePlaying}>
<play-arrow-icon-sk ?hidden=${ele.playing}></play-arrow-icon-sk>
<pause-icon-sk ?hidden=${!ele.playing}></pause-icon-sk>
</button>
<span id=ms>${ele.time.toFixed(3)}</span>
<span>${ele._uniform.name}</span>
`;
connectedCallback(): void {
super.connectedCallback();
this._render();
this.startTime = this.dateNow();
this.time = 0;
}
render(): void {
this._render();
}
/** Copies the values of the control into the uniforms array. */
applyUniformValues(uniforms: number[]): void {
uniforms[this._uniform.slot] = this.time;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
restoreUniformValues(uniforms: number[]): void {
// This is a noop, we don't restore predefined uniform values.
}
onRAF(): void {
this.render();
}
needsRAF(): boolean {
return true;
}
/** Allows overriding the Date.now function for testing. */
get dateNow(): DateNow {
return this._dateNow;
}
set dateNow(val: DateNow) {
this._dateNow = val;
}
/** The current time offset in seconds. */
get time(): number {
if (!this.playing) {
return this.pauseTime;
}
return (this.dateNow() - this.startTime) / 1000;
}
set time(val: number) {
this.pauseTime = val;
this.startTime = this.dateNow() - val * 1000;
}
/** The description of the uniform. */
get uniform(): Uniform {
return this._uniform;
}
set uniform(val: Uniform) {
if (val.rows !== 1 || val.columns !== 1) {
throw new Error('Invalid time uniform dimensions.');
}
this._uniform = val;
this._render();
}
private restart() {
this.time = 0;
this.pauseTime = 0;
this._render();
}
private togglePlaying() {
if (this.playing) {
this.pauseTime = this.time;
} else {
this.time = this.pauseTime;
}
this.playing = !this.playing;
this._render();
}
}
define('uniform-time-sk', UniformTimeSk);