Skip to content

⬅️ Back to Table of Contents

📄 useGamepad

📊 Analysis Summary

Metric Count
🔧 Functions 6
📦 Imports 14
🟢 Vue Composition API 1
📐 Interfaces 2

📚 Table of Contents

🛠️ File Location:

📂 packages/core/useGamepad/index.ts

📦 Imports

Name Source
EventHookOn @vueuse/shared
Pausable @vueuse/shared
Ref vue
ConfigurableNavigator ../_configurable
ConfigurableWindow ../_configurable
Supportable ../types
createEventHook @vueuse/shared
tryOnMounted @vueuse/shared
computed vue
deepRef vue
defaultNavigator ../_configurable
useEventListener ../useEventListener
useRafFn ../useRafFn
useSupported ../useSupported

Vue Composition API

Name Type Reactive Variables Composables
computed computed none none

Functions

mapGamepadToXbox360Controller(gamepad: Ref<Gamepad | undefined>): any

Maps a standard standard gamepad to an Xbox 360 Controller.

Raw JSDoc
/**
 * Maps a standard standard gamepad to an Xbox 360 Controller.
 */

Calls:

  • computed (from vue)
Code
export function mapGamepadToXbox360Controller(gamepad: Ref<Gamepad | undefined>) {
  return computed(() => {
    if (gamepad.value) {
      return {
        buttons: {
          a: gamepad.value.buttons[0],
          b: gamepad.value.buttons[1],
          x: gamepad.value.buttons[2],
          y: gamepad.value.buttons[3],
        },
        bumper: {
          left: gamepad.value.buttons[4],
          right: gamepad.value.buttons[5],
        },
        triggers: {
          left: gamepad.value.buttons[6],
          right: gamepad.value.buttons[7],
        },
        stick: {
          left: {
            horizontal: gamepad.value.axes[0],
            vertical: gamepad.value.axes[1],
            button: gamepad.value.buttons[10],
          },
          right: {
            horizontal: gamepad.value.axes[2],
            vertical: gamepad.value.axes[3],
            button: gamepad.value.buttons[11],
          },
        },
        dpad: {
          up: gamepad.value.buttons[12],
          down: gamepad.value.buttons[13],
          left: gamepad.value.buttons[14],
          right: gamepad.value.buttons[15],
        },
        back: gamepad.value.buttons[8],
        start: gamepad.value.buttons[9],
      }
    }

    return null
  })
}

useGamepad(options: UseGamepadOptions): UseGamepadReturn

Parameters:

  • options UseGamepadOptions

Returns: UseGamepadReturn

Calls:

  • useSupported (from ../useSupported)
  • deepRef (from vue)
  • createEventHook (from @vueuse/shared)
  • hapticActuators.push
  • gamepad.axes.map
  • gamepad.buttons.map
  • navigator?.getGamepads
  • gamepads.value.findIndex
  • stateFromGamepad
  • useRafFn (from ../useRafFn)
  • gamepads.value.some
  • gamepads.value.push
  • onConnectedHook.trigger
  • resume
  • gamepads.value.filter
  • onDisconnectedHook.trigger
  • useEventListener (from ../useEventListener)
  • onGamepadConnected
  • onGamepadDisconnected
  • tryOnMounted (from @vueuse/shared)
  • pause

Internal Comments:

// @ts-expect-error missing in types (x5)

Code
export function useGamepad(options: UseGamepadOptions = {}): UseGamepadReturn {
  const {
    navigator = defaultNavigator,
  } = options
  const isSupported = useSupported(() => navigator && 'getGamepads' in navigator)
  const gamepads = deepRef<Gamepad[]>([])

  const onConnectedHook = createEventHook<number>()
  const onDisconnectedHook = createEventHook<number>()

  const stateFromGamepad = (gamepad: Gamepad) => {
    const hapticActuators = []
    const vibrationActuator = 'vibrationActuator' in gamepad ? (gamepad as Gamepad).vibrationActuator : null

    if (vibrationActuator)
      hapticActuators.push(vibrationActuator)

    // @ts-expect-error missing in types
    if (gamepad.hapticActuators)
      // @ts-expect-error missing in types
      hapticActuators.push(...gamepad.hapticActuators)

    return {
      id: gamepad.id,
      index: gamepad.index,
      connected: gamepad.connected,
      mapping: gamepad.mapping,
      timestamp: gamepad.timestamp,
      vibrationActuator: gamepad.vibrationActuator,
      hapticActuators,
      axes: gamepad.axes.map(axes => axes),
      buttons: gamepad.buttons.map(button => ({ pressed: button.pressed, touched: button.touched, value: button.value })),
    } as Gamepad
  }

  const updateGamepadState = () => {
    const _gamepads = navigator?.getGamepads() || []

    for (const gamepad of _gamepads) {
      if (!gamepad)
        continue

      const index = gamepads.value.findIndex(x => x.index === gamepad.index)
      if (index > -1)
        gamepads.value[index] = stateFromGamepad(gamepad)
    }
  }

  const { isActive, pause, resume } = useRafFn(updateGamepadState)

  const onGamepadConnected = (gamepad: Gamepad) => {
    if (!gamepads.value.some(({ index }) => index === gamepad.index)) {
      gamepads.value.push(stateFromGamepad(gamepad))
      onConnectedHook.trigger(gamepad.index)
    }

    resume()
  }

  const onGamepadDisconnected = (gamepad: Gamepad) => {
    gamepads.value = gamepads.value.filter(x => x.index !== gamepad.index)
    onDisconnectedHook.trigger(gamepad.index)
  }

  const listenerOptions = { passive: true }
  useEventListener('gamepadconnected', e => onGamepadConnected(e.gamepad), listenerOptions)
  useEventListener('gamepaddisconnected', e => onGamepadDisconnected(e.gamepad), listenerOptions)

  tryOnMounted(() => {
    const _gamepads = navigator?.getGamepads() || []

    for (const gamepad of _gamepads) {
      if (gamepad && gamepads.value[gamepad.index])
        onGamepadConnected(gamepad)
    }
  })

  pause()

  return {
    isSupported,
    onConnected: onConnectedHook.on,
    onDisconnected: onDisconnectedHook.on,
    gamepads,
    pause,
    resume,
    isActive,
  }
}

Internal helpers

Declared inside another function in this file.

stateFromGamepad(gamepad: Gamepad): Gamepad

Parameters:

  • gamepad Gamepad

Returns: Gamepad

Calls:

  • hapticActuators.push
  • gamepad.axes.map
  • gamepad.buttons.map

Internal Comments:

// @ts-expect-error missing in types (x5)

Code
(gamepad: Gamepad) => {
    const hapticActuators = []
    const vibrationActuator = 'vibrationActuator' in gamepad ? (gamepad as Gamepad).vibrationActuator : null

    if (vibrationActuator)
      hapticActuators.push(vibrationActuator)

    // @ts-expect-error missing in types
    if (gamepad.hapticActuators)
      // @ts-expect-error missing in types
      hapticActuators.push(...gamepad.hapticActuators)

    return {
      id: gamepad.id,
      index: gamepad.index,
      connected: gamepad.connected,
      mapping: gamepad.mapping,
      timestamp: gamepad.timestamp,
      vibrationActuator: gamepad.vibrationActuator,
      hapticActuators,
      axes: gamepad.axes.map(axes => axes),
      buttons: gamepad.buttons.map(button => ({ pressed: button.pressed, touched: button.touched, value: button.value })),
    } as Gamepad
  }

updateGamepadState(): void

Returns: void

Calls:

  • navigator?.getGamepads
  • gamepads.value.findIndex
  • stateFromGamepad
Code
() => {
    const _gamepads = navigator?.getGamepads() || []

    for (const gamepad of _gamepads) {
      if (!gamepad)
        continue

      const index = gamepads.value.findIndex(x => x.index === gamepad.index)
      if (index > -1)
        gamepads.value[index] = stateFromGamepad(gamepad)
    }
  }

onGamepadConnected(gamepad: Gamepad): void

Parameters:

  • gamepad Gamepad

Returns: void

Calls:

  • gamepads.value.some
  • gamepads.value.push
  • stateFromGamepad
  • onConnectedHook.trigger
  • resume
Code
(gamepad: Gamepad) => {
    if (!gamepads.value.some(({ index }) => index === gamepad.index)) {
      gamepads.value.push(stateFromGamepad(gamepad))
      onConnectedHook.trigger(gamepad.index)
    }

    resume()
  }

onGamepadDisconnected(gamepad: Gamepad): void

Parameters:

  • gamepad Gamepad

Returns: void

Calls:

  • gamepads.value.filter
  • onDisconnectedHook.trigger
Code
(gamepad: Gamepad) => {
    gamepads.value = gamepads.value.filter(x => x.index !== gamepad.index)
    onDisconnectedHook.trigger(gamepad.index)
  }

Interfaces

UseGamepadOptions

Interface Code
export interface UseGamepadOptions extends ConfigurableWindow, ConfigurableNavigator {

}

UseGamepadReturn

Interface Code
export interface UseGamepadReturn extends Supportable, Pausable {
  onConnected: EventHookOn<number>
  onDisconnected: EventHookOn<number>
  gamepads: Ref<Gamepad[]>
}

Properties

Name Type Optional Description
onConnected EventHookOn<number> not shown
onDisconnected EventHookOn<number> not shown
gamepads Ref<Gamepad[]> not shown

Generated by Syntax Scribe