memlnaut-nisps/manifold/src/inputs/xy-pad-source.ts

57 lines
1.4 KiB
TypeScript
Raw Normal View History

/**
* XYPadSource the existing on-screen XY pad / joystick / manifold drag,
* wrapped as a 2-axis InputSource.
*
* Push-based: the pad's `onMove(x, y)` handler calls `pushAxes(x, y)`, which
* latches the values. `sample()` reads them back through the standard pull path
* so the XY pad composes identically with poll-based sources (MIDI/gamepad).
*
* This is always available (it's an on-screen widget), so it starts `ready`.
*/
import { BaseSource } from './base-source';
import type { InputSourceKind } from './types';
export class XYPadSource extends BaseSource {
readonly kind: InputSourceKind = 'xy-pad';
readonly label = 'XY pad';
private x = 0.5;
private y = 0.5;
constructor() {
super({ state: 'ready', message: 'XY pad ready' });
}
axisCount(): number {
return 2;
}
axisLabels(): string[] {
return ['X', 'Y'];
}
/** Latch the latest pad position (∈ [0,1]). Called from the pad's onMove. */
pushAxes(x: number, y: number): void {
this.x = clamp01(x);
this.y = clamp01(y);
}
sample(out: Float32Array, offset: number): number {
out[offset] = this.x;
out[offset + 1] = this.y;
return 2;
}
start(): void {
this.setStatus({ state: 'ready', message: 'XY pad ready' });
}
stop(): void {
this.setStatus({ state: 'idle', message: 'XY pad off' });
}
}
function clamp01(v: number): number {
return v < 0 ? 0 : v > 1 ? 1 : v;
}