From 8e6e18f41386183a5df5c12824b4a07c8f4c8cdb Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Tue, 19 May 2020 08:21:33 -0600 Subject: [PATCH] Add gamepad support + Enter=straight --- static/index.html | 20 +++++++-- static/vail.css | 22 +++++++++ static/vail.js | 112 ++++++++++++++++++++++++++++++++-------------- 3 files changed, 117 insertions(+), 37 deletions(-) diff --git a/static/index.html b/static/index.html index e9f1cc8..7e68238 100644 --- a/static/index.html +++ b/static/index.html @@ -77,7 +77,13 @@ - c or , or ⇧ Shift + c + , + Enter + ⇧ Shift +
+ A + B @@ -98,12 +104,20 @@ - . or z + . + z +
+ X + LB
right-click for Dah - / or x + / + x +
+ Y + RB diff --git a/static/vail.css b/static/vail.css index ad7c39b..a3aad3b 100644 --- a/static/vail.css +++ b/static/vail.css @@ -55,6 +55,28 @@ kbd { border-radius: 3px; font-size: 9pt; padding: .1em .6em; + cursor: default; +} + +.gamepad { + color: white; + font-weight: bold; + background-color: #444; + border-radius: 50%; + height: 10px; + width: 10px; +} +.gamepad.a { + color: #8f8; +} +.gamepad.b { + color: #f88; +} +.gamepad.x { + color: #88f; +} +.gamepad.y { + color: #ff8; } code { diff --git a/static/vail.js b/static/vail.js index fce7d99..5688ae1 100644 --- a/static/vail.js +++ b/static/vail.js @@ -262,8 +262,8 @@ class Vail { } // Listen for keystrokes - document.addEventListener("keydown", e => this.key(e)) - document.addEventListener("keyup", e => this.key(e)) + document.addEventListener("keydown", e => this.keyboard(e)) + document.addEventListener("keyup", e => this.keyboard(e)) // Make helpers this.iambic = new Iambic(() => this.beginTx(), () => this.endTx()) @@ -282,19 +282,9 @@ class Vail { navigator.requestMIDIAccess() .then(a => this.midiInit(a)) } - } - - maximize(e) { - let element = e.target - while (! element.classList.contains("mdl-card")) { - element = element.parentElement - if (! element) { - console.log("Maximize button: couldn't find parent card") - return - } - } - element.classList.toggle("maximized") - console.log(element) + + // Set up for gamepad input + window.addEventListener("gamepadconnected", e => this.gamepadConnected(e)) } openSocket() { @@ -368,14 +358,9 @@ class Vail { return } } - + error(msg) { - let now = new Date() - let el = document.querySelector("#snackbar") - el.MaterialSnackbar.showSnackbar({ - message: msg, - timeout: 2000 - }) + toast(msg) this.buzzer.ErrorTone() } @@ -483,8 +468,16 @@ class Vail { this.endTx() } } + + iambicDit(begin) { + this.iambic.Key(begin, DIT) + } + + iambicDah(begin) { + this.iambic.Key(begin, DAH) + } - key(event) { + keyboard(event) { if (event.repeat) { // Ignore key repeats generated by the OS, we do this ourselves return @@ -494,19 +487,19 @@ class Vail { if ((event.code == "KeyZ") || (event.code == "Period")) { event.preventDefault() - this.iambic.Key(begin, DIT) + this.iambicDit(begin) } if ((event.code == "KeyX") || (event.code == "Slash")) { event.preventDefault() - this.iambic.Key(begin, DAH) + this.iambicDah(begin) } - if ((event.code == "KeyC") || (event.code == "Comma") || (event.key == "Shift")) { + if ((event.code == "KeyC") || + (event.code == "Comma") || + (event.key == "Shift") || + (event.key == "Enter") || + (event.key == "NumpadEnter")) { event.preventDefault() - if (begin) { - this.beginTx() - } else { - this.endTx() - } + this.straightKey(begin) } } @@ -516,11 +509,11 @@ class Vail { event.preventDefault() if (event.target.id == "dah") { - this.iambic.Key(begin, DAH) + this.iambicDah(begin) } else if ((event.target.id == "dit") && (event.button == 2)) { - this.iambic.Key(begin, DAH) + this.iambicDah(begin) } else if (event.target.id == "dit") { - this.iambic.Key(begin, DIT) + this.iambigDit(begin) } else if (event.target.id == "key") { this.straightKey(begin) } else if ((event.target.id == "ck") && begin) { @@ -528,6 +521,42 @@ class Vail { } } + + gamepadConnected(event) { + // Polling could be computationally expensive, + // especially on devices with a power budget, like phones. + // To be considerate, we only start polling if a gamepad appears. + if (! this.gamepadButtons) { + this.gamepadButtons = {} + this.gamepadPoll(event.timeStamp) + } + } + + gamepadPoll(timestamp) { + let currentButtons = {} + for (let gp of navigator.getGamepads()) { + if (gp == null) { + continue + } + currentButtons.key |= gp.buttons[0].pressed || gp.buttons[1].pressed + currentButtons.dit |= gp.buttons[2].pressed || gp.buttons[4].pressed + currentButtons.dah |= gp.buttons[3].pressed || gp.buttons[5].pressed + } + + if (currentButtons.key != this.gamepadButtons.key) { + this.straightKey(currentButtons.key) + } + if (currentButtons.dit != this.gamepadButtons.dit) { + this.iambicDit(currentButtons.dit) + } + if (currentButtons.dah != this.gamepadButtons.dah) { + this.iambicDah(currentButtons.dah) + } + this.gamepadButtons = currentButtons + + requestAnimationFrame(e => this.gamepadPoll(e)) + } + /** * Send "CK" to server, and don't squelch the repeat */ @@ -545,6 +574,21 @@ class Vail { this.wsSend(Date.now(), 0) // Get round-trip time this.socket.send(JSON.stringify(msg)) } + + maximize(e) { + let element = e.target + while (! element.classList.contains("mdl-card")) { + element = element.parentElement + if (! element) { + console.log("Maximize button: couldn't find parent card") + return + } + } + element.classList.toggle("maximized") + console.log(element) + } + + } function vailInit() {