blob: 41d028ecc0f2353cdae4b6f9dd290cec8620ccc8 [file] [log] [blame]
/**
* @module modules/uniform-mouse-sk
* @description <h2><code>uniform-mouse-sk</code></h2>
*
* Control to handle mouse position and clicks as a uniform.
*
* Note this control doesn't display anything.
*
* See https://www.shadertoy.com/view/Mss3zH for an explanation of how the
* iMouse uniform behaves.
*/
import { define } from 'elements-sk/define';
import { Uniform, UniformControl } from '../uniform/uniform';
const defaultUniform: Uniform = {
name: 'iMouse',
rows: 4,
columns: 1,
slot: 0,
};
export class UniformMouseSk extends HTMLElement implements UniformControl {
private _uniform: Uniform = defaultUniform;
private _elementToMonitor: HTMLElement | null = null;
private location: [number, number] = [0, 0];
private lastClick: [number, number] = [1, 1];
private mouseDown: boolean = false;
private mouseClick: boolean = false;
applyUniformValues(uniforms: number[]): void {
uniforms[this._uniform.slot] = this.location[0];
uniforms[this._uniform.slot + 1] = this.location[1];
uniforms[this._uniform.slot + 2] = Math.abs(this.lastClick[0]) * (this.mouseDown ? 1 : -1);
uniforms[this._uniform.slot + 3] = Math.abs(this.lastClick[1]) * (this.mouseClick ? 1 : -1);
}
// 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 {
// noop.
}
needsRAF(): boolean {
return false;
}
get elementToMonitor(): HTMLElement {
return this._elementToMonitor!;
}
set elementToMonitor(val: HTMLElement) {
if (this.elementToMonitor === val) {
return;
}
if (this.elementToMonitor) {
this._elementToMonitor!.removeEventListener('mouseup', this.mouseUpHandler.bind(this));
this._elementToMonitor!.removeEventListener('mousedown', this.mouseDownHandler.bind(this));
this._elementToMonitor!.removeEventListener('mousemove', this.mouseMoveHandler.bind(this));
this._elementToMonitor!.removeEventListener('click', this.clickHandler.bind(this));
}
this._elementToMonitor = val;
this._elementToMonitor!.addEventListener('mouseup', this.mouseUpHandler.bind(this));
this._elementToMonitor!.addEventListener('mousedown', this.mouseDownHandler.bind(this));
this._elementToMonitor!.addEventListener('mousemove', this.mouseMoveHandler.bind(this));
this._elementToMonitor!.addEventListener('click', this.clickHandler.bind(this));
}
private mouseUpHandler(e: MouseEvent) {
this.mouseDown = false;
this.location = [e.offsetX, e.offsetY];
}
private mouseDownHandler(e: MouseEvent) {
this.mouseDown = true;
this.location = [e.offsetX, e.offsetY];
}
private mouseMoveHandler(e: MouseEvent) {
if (this.mouseDown) {
this.location = [e.offsetX, e.offsetY];
}
}
private clickHandler(e: MouseEvent) {
this.lastClick = [e.offsetX, e.offsetY];
this.mouseClick = true;
}
get uniform(): Uniform {
return this._uniform;
}
set uniform(val: Uniform) {
if (val.columns !== 4 || val.rows !== 1) {
throw new Error('The mouse uniform must be a float4.');
}
this._uniform = val;
}
}
define('uniform-mouse-sk', UniformMouseSk);