NoriginMedia / Norigin-Spatial-Navigation

React Hooks based Spatial Navigation (Key & Remote Control Navigation) / Web Browsers, Smart TVs and Connected TVs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Detect gamepad inputs or add a way of triggering arrows / enter

ChocolateLoverRaj opened this issue · comments

Is your feature request related to a problem? Please describe.
I want this library to work on Xbox. The Xbox supports the Gamepad API. However, this library only supports keyboard events.

Describe the solution you'd like

Automatic

Detects when 'A' (or another button for other controllers) and plus pad buttons are pressed, and does the navigation according to the gamepad

Custom

Export functions or hooks:

import { move } from '@noriginmedia/norigin-spatial-navigation'

move('up')
move('enter')

Describe alternatives you've considered
Here is my current work-around (which works), which will probably be useful to others even if this issue doesn't get solved:

// Dispatches keyup and keydown events for arrow keys and enter when the first gamepad uses plus pad and A button
let animationFrame: number | undefined
addEventListener('gamepadconnected', () => {
  // Only run loop if it's not already running
  if (animationFrame === undefined) {
    console.log('check')
    // Left, right, up, down, A
    const pressedButtons = [false, false, false, false, false]
    const keyCodes = [37, 39, 38, 40, 13]
    const buttons = [14, 15, 12, 13, 0]
    const check = (): void => {
      for (let i = 0; i < pressedButtons.length; i++) {
        const pressed = navigator.getGamepads()[0]?.buttons[buttons[i]].pressed ?? false
        if (pressed && !pressedButtons[i]) {
          dispatchEvent(new KeyboardEvent('keydown', { keyCode: keyCodes[i] }))
        } else if (!pressed && pressedButtons[i]) {
          dispatchEvent(new KeyboardEvent('keyup', { keyCode: keyCodes[i] }))
        }
        pressedButtons[i] = pressed
      }
      animationFrame = requestAnimationFrame(check)
    }
    check()
  }
})
addEventListener('gamepaddisconnected', () => {
  cancelAnimationFrame(animationFrame as number)
  animationFrame = undefined
})

I prefer to not use dispatchEvent with the keyboard keyCodes though.

Additional context
Add any other context or screenshots about the feature request here.

Hello.

Thank you for the proposal and for the idea of how to handle the gamepad navigation.

Similar to discussions around Back Button, after multiple internal discussions, we concluded that we probably wouldn't want to extend the library to handle more buttons and/or input device as this will bloat the library. We would like to keep it as simple as possible and device-agnostic.
Some related explanations here: #57

We also have a navigateByDirection method which allows manually navigating up/down/left/right, which might help with this and can be easily wired to any input device. For example we are using it to map the scroll wheel to "up" and "down" triggers.