feat(playground): expand gamepad support with face buttons and Steam Deck fixes
- Map A=Train, B=Clear Examples, X=Randomize, LB=Thumbs Down, RB=Thumbs Up - Add periodic gamepad polling fallback for environments where gamepadconnected event doesn't fire reliably (Steam Deck, some Linux browsers) - Show "Press any gamepad button to connect" hint on page load
This commit is contained in:
parent
affec8f604
commit
de75a3f0e4
4 changed files with 50 additions and 17 deletions
|
|
@ -1365,14 +1365,23 @@ function wireGamepad() {
|
||||||
onJoystickMove();
|
onJoystickMove();
|
||||||
},
|
},
|
||||||
onButton: (btn) => {
|
onButton: (btn) => {
|
||||||
if (btn === 'rb') onThumbsUp();
|
|
||||||
if (btn === 'lb') onThumbsDown();
|
if (btn === 'lb') onThumbsDown();
|
||||||
|
if (btn === 'rb') onThumbsUp();
|
||||||
|
if (btn === 'a') onTrain();
|
||||||
|
if (btn === 'x') onRandomize();
|
||||||
|
if (btn === 'b') onClearExamples();
|
||||||
},
|
},
|
||||||
onConnectionChange: (connected) => {
|
onConnectionChange: (connected) => {
|
||||||
const el = document.getElementById('gamepad-status');
|
const el = document.getElementById('gamepad-status');
|
||||||
if (el) el.textContent = connected ? 'Gamepad connected' : '';
|
if (el) el.textContent = connected ? 'Gamepad connected' : 'Press any button to activate gamepad';
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Show hint immediately if no gamepad detected yet
|
||||||
|
if (!gamepad.connected) {
|
||||||
|
const el = document.getElementById('gamepad-status');
|
||||||
|
if (el) el.textContent = 'Press any gamepad button to connect';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Keyboard ----
|
// ---- Keyboard ----
|
||||||
|
|
|
||||||
|
|
@ -1241,15 +1241,23 @@ function init() {
|
||||||
mappingView.drawOverlay();
|
mappingView.drawOverlay();
|
||||||
},
|
},
|
||||||
onButton: (btn) => {
|
onButton: (btn) => {
|
||||||
if (btn === 'rb') onThumbsUp();
|
|
||||||
if (btn === 'lb') onThumbsDown();
|
if (btn === 'lb') onThumbsDown();
|
||||||
|
if (btn === 'rb') onThumbsUp();
|
||||||
|
if (btn === 'a') onTrain();
|
||||||
|
if (btn === 'x') onRandomize();
|
||||||
|
if (btn === 'b') onClearExamples();
|
||||||
},
|
},
|
||||||
onConnectionChange: (connected) => {
|
onConnectionChange: (connected) => {
|
||||||
const el = document.getElementById('gamepad-status');
|
const el = document.getElementById('gamepad-status');
|
||||||
if (el) el.textContent = connected ? 'Gamepad connected' : '';
|
if (el) el.textContent = connected ? 'Gamepad connected' : 'Press any button to activate gamepad';
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!gamepad.connected) {
|
||||||
|
const el = document.getElementById('gamepad-status');
|
||||||
|
if (el) el.textContent = 'Press any gamepad button to connect';
|
||||||
|
}
|
||||||
|
|
||||||
// Resize
|
// Resize
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
visualizer.resize();
|
visualizer.resize();
|
||||||
|
|
|
||||||
|
|
@ -287,15 +287,20 @@ function init() {
|
||||||
drawJoystick();
|
drawJoystick();
|
||||||
},
|
},
|
||||||
onButton: (btn) => {
|
onButton: (btn) => {
|
||||||
if (btn === 'rb') onThumbsUp();
|
|
||||||
if (btn === 'lb') onThumbsDown();
|
if (btn === 'lb') onThumbsDown();
|
||||||
|
if (btn === 'rb') onThumbsUp();
|
||||||
},
|
},
|
||||||
onConnectionChange: (connected) => {
|
onConnectionChange: (connected) => {
|
||||||
const el = document.getElementById('gamepad-status');
|
const el = document.getElementById('gamepad-status');
|
||||||
if (el) el.textContent = connected ? 'Gamepad connected' : '';
|
if (el) el.textContent = connected ? 'Gamepad connected' : 'Press any button to activate gamepad';
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!gamepad.connected) {
|
||||||
|
const el = document.getElementById('gamepad-status');
|
||||||
|
if (el) el.textContent = 'Press any gamepad button to connect';
|
||||||
|
}
|
||||||
|
|
||||||
// Follow mode wiring
|
// Follow mode wiring
|
||||||
wireFollowMode();
|
wireFollowMode();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,17 @@ export class GamepadInput {
|
||||||
|
|
||||||
// Check if a gamepad is already connected
|
// Check if a gamepad is already connected
|
||||||
this._findGamepad();
|
this._findGamepad();
|
||||||
|
|
||||||
|
// Periodic fallback: some environments (Steam Deck, some Linux browsers)
|
||||||
|
// don't fire gamepadconnected reliably. Poll every 500ms until found.
|
||||||
|
this._probeInterval = setInterval(() => {
|
||||||
|
if (!this.connected) {
|
||||||
|
this._findGamepad();
|
||||||
|
} else {
|
||||||
|
clearInterval(this._probeInterval);
|
||||||
|
this._probeInterval = null;
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onConnected(e) {
|
_onConnected(e) {
|
||||||
|
|
@ -126,18 +137,17 @@ export class GamepadInput {
|
||||||
this.onMove(mappedX, mappedY);
|
this.onMove(mappedX, mappedY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buttons: LB=4, RB=5
|
// Buttons: A=0, B=1, X=2, Y=3, LB=4, RB=5
|
||||||
if (this.onButton) {
|
if (this.onButton) {
|
||||||
const lbPressed = !!gp.buttons[4]?.pressed;
|
const watched = [0, 1, 2, 3, 4, 5];
|
||||||
const rbPressed = !!gp.buttons[5]?.pressed;
|
const names = ['a', 'b', 'x', 'y', 'lb', 'rb'];
|
||||||
const lbPrev = !!this._buttonsPrev[4];
|
for (let i = 0; i < watched.length; i++) {
|
||||||
const rbPrev = !!this._buttonsPrev[5];
|
const idx = watched[i];
|
||||||
|
const pressed = !!gp.buttons[idx]?.pressed;
|
||||||
if (lbPressed && !lbPrev) this.onButton('lb');
|
const prev = !!this._buttonsPrev[idx];
|
||||||
if (rbPressed && !rbPrev) this.onButton('rb');
|
if (pressed && !prev) this.onButton(names[i]);
|
||||||
|
this._buttonsPrev[idx] = pressed;
|
||||||
this._buttonsPrev[4] = lbPressed;
|
}
|
||||||
this._buttonsPrev[5] = rbPressed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return moved;
|
return moved;
|
||||||
|
|
@ -153,5 +163,6 @@ export class GamepadInput {
|
||||||
destroy() {
|
destroy() {
|
||||||
window.removeEventListener('gamepadconnected', this._onConnected);
|
window.removeEventListener('gamepadconnected', this._onConnected);
|
||||||
window.removeEventListener('gamepaddisconnected', this._onDisconnected);
|
window.removeEventListener('gamepaddisconnected', this._onDisconnected);
|
||||||
|
if (this._probeInterval) clearInterval(this._probeInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue