Extensions to the base Gamepad specification to enable access to more advanced device capabilities.
If you have comments for this spec, please send them to public-webapps@w3.org with a Subject: prefix of [gamepad]. See Bugzilla for this specification's open bugs.

Introduction

The Gamepad API provides a tightly scoped interface to gamepad devices and is focused on the most common elements of those devices, namely axis and button inputs. It specifically excludes support for more complex devices (e.g., those that do motion tracking or haptic feedback).

However, some uses of gamepads (e.g., those paired with Virtual Reality headsets) rely heavily on those more advanced features. This supplemetary spec describes extensions to the base API to accommodate those use cases. If they prove to be broadly useful, the hope is that they will be eventually merged into the main spec.

GamepadHand Enum

This enum defines the set of possible hands a gamepad may be held by.

        enum GamepadHand {
          "",  /* unknown, both hands, or not applicable */
          "left",
          "right"
        };
      
"" (the empty string)
The empty string indicates the hand that is holding the gamepad is unknown or not applicable (e.g., if the gamepad is held with two hands).
left
Gamepad is held or is most likely to be held in the left hand.
right
Gamepad is held or is most likely to be held in the right hand.

GamepadPose Interface

This interface defines the gamepad's position, orientation, velocity, and acceleration.

        [Exposed=Window]
        interface GamepadPose {
          readonly attribute boolean hasOrientation;
          readonly attribute boolean hasPosition;

          readonly attribute Float32Array? position;
          readonly attribute Float32Array? linearVelocity;
          readonly attribute Float32Array? linearAcceleration;
          readonly attribute Float32Array? orientation;
          readonly attribute Float32Array? angularVelocity;
          readonly attribute Float32Array? angularAcceleration;
        };
      
hasOrientation
The hasOrientation attribute MUST return whether the gamepad is capable of tracking its orientation.
hasPosition
The hasPosition attribute MUST return whether the gamepad is capable of tracking its position.
position

Position of the gamepad as a 3D vector, given in meters from an origin point, which is determined by the gamepad hardware and MAY be the position of the gamepad when first polled if no other reference point is available. The coordinate system uses these axis definitions, assuming the user is holding the gamepad in the forward orientation:

  • Positive X is to the user's right.
  • Positive Y is up.
  • Positive Z is behind the user.

MUST be null if the gamepad is incapable of providing positional data. When not null, MUST be a three-element array.

linearVelocity
Linear velocity of the gamepad in meters per second. MUST be null if the sensor is incapable of providing linear velocity. When not null, MUST be a three-element array.
linearAcceleration
Linear acceleration of the gamepad in meters per second. MUST be null if the sensor is incapable of providing linear acceleration. When not null, MUST be a three-element array.
orientation
Orientation of the gamepad as a quaternion. An orientation of [0, 0, 0, 1] is considered to be forward. The forward direction MUST be determined by the gamepad hardware. The forward direction MAY be the orientation of the hardware when it was first polled if no other reference orientation is available. If the sensor is incapable of providing orientation data, the orientation MUST be null. When not null, the orientation MUST be a four-element array.
angularVelocity
Angular velocity of the gamepad in meters per second. MUST be null if the sensor is incapable of providing angular velocity. When not null, the angularVelocity MUST be a three-element array.
angularAcceleration
Angular acceleration of the gamepad in meters per second. MUST be null if the sensor is incapable of providing angular acceleration. When not null, angularAcceleration MUST be a three-element array.

GamepadTouch Interface

This interface defines a single touch event on a gamepad device that supports input. The event consists of a touch id that uniquely identifies the touch point from the time the input medium (e.g. finger, stylus, etc) makes contact with the touch device, up to the time the input medium is no longer making contact with the touch device.

        [Exposed=Window, SecureContext]
        interface GamepadTouch {
          readonly attribute unsigned long touchId;
          readonly attribute octet surfaceId;
          readonly attribute Float32Array position;
          readonly attribute Uint32Array? surfaceDimensions;
        };
      
touchId attribute
Unique id of the touch event. Range is [0, 4294967295].

The user agent is responsible for:

  • Incrementing the id for each subsequent touch event based on information provided by the device API.
  • Maintaining the uniqueness of the id per origin to prevent fingerprinting.
{{GamepadTouch/touchId}} SHOULD be set to a default value of 0 when a new {{Gamepad}} object is created.
surfaceId
Unique id of the surface that generated the touch event.
position
x, y coordinates of the touch event. Range of each coordinate is normalized to [-1.0, 1.0]. Along the x-axis, -1.0 references the leftmost coordinate and 1.0 references the rightmost coordinate. Along the y-axis, -1.0 references the topmost coordinate and 1.0 references the bottommost coordinate. MUST be a two-element array.
surfaceDimensions
Width and height of the touch surface in integer units. When not null, MUST be a two-element array.

Partial Gamepad Interface

This partial interface supplements the Gamepad interface described in the main Gamepad spec.

        partial interface Gamepad {
          readonly attribute GamepadHand hand;
          readonly attribute FrozenArray<GamepadHapticActuator> hapticActuators;
          readonly attribute GamepadPose? pose;
          readonly attribute FrozenArray<GamepadTouch>? touchEvents;
        };
      

Instances of {{Gamepad}} are created with the internal slots described in the following table:

Internal slot Initial value Description (non-normative)
[[\hand]] `undefined` Indicates the hand the controller is held in.
[[\hapticActuators]] `undefined` List of all the haptic actuators in the gamepad.
[[\pose]] `null` The current pose of the gamepad.
[[\touchEvents]] `null` List of generated touch events.
hand
An enumeration, {{GamepadHand}}, that indicates which hand the controller is being held in or is most likely to be held in.
hapticActuators
A list of all the {{GamepadHapticActuator}}s in the gamepad. The same object MUST be returned until the user agent needs to return different values (or values in a different order).
pose
The current {{GamepadPose}} of the gamepad, if supported by the hardware. Includes position, orientation, velocity, and acceleration. If the hardware cannot supply any pose values, MUST be set to `null`.
touchEvents

A list of {{GamepadTouch}} events generated from all touch surfaces. If the device does not support touch events, MUST be set to `null`.

The {{Gamepad/touchEvents}} getter steps are:

  1. If [=this=].{{Gamepad/[[touchEvents]]}} not `null` and not empty, return [=this=].{{Gamepad/[[touchEvents]]}}.
  2. Otherwise return `null`.

Receiving inputs

This section supplements the Receiving inputs section of the main Gamepad specification.

In addtion to the steps defined in the main Gamepad specification. When the user agent modifies the list of |active touch points| for a touch surface by adding touch points, removing touch points, or updating the values of existing touch points, update touchEvents by running the following steps:

  1. Let |surfaceId:unsigned long| be 0.
  2. Remove any existing events from {{Gamepad}}.{{Gamepad/[[touchEvents]]}}.
  3. Repeat the following steps for each [=touch surface=] on |gamepad| in [=touch surface enumeration order=]:
    1. Let |surfaceDimensions| be an `null`.
    2. If the touch surface exposes maximum surface dimensions in device units:
      1. Set |touchEvent|.{{GamepadTouch/surfaceDimensions}}[0] to the maximum X dimension on the [=touch surface=] in device units.
      2. Set |touchEvent|.{{GamepadTouch/surfaceDimensions}}[1] to the maximum Y dimension on the [=touch surface=] in device units.
    3. Repeat the following steps for each [=active touch point=] reported by the |gamepad| for the current [=touch surface=].
      1. Let |nextTouchId:unsigned long| be the next available touchId for the |gamepad|.
      2. Let |touchEvent:GamepadTouch| be a {{GamepadTouch}}.
      3. Set |touchEvent|.{{GamepadTouch/surfaceId}} to be |surfaceId|.
      4. If the touch data is part of an existing [=active touch point=] tracked by the user agent:
        1. Set |touchEvent|.{{GamepadTouch/touchId}} to the touchId of the [=active touch point=].
        2. Otherwise, set touchId to nextTouchId and increment nextTouchId.

          If the Gamepad has multiple touch surfaces the touch id will be unique across surfaces.

      5. Let |position| be a [=new=] {{Float32Array}} with length 2.
      6. |position|[0] should be set to the device X coordinate relative to the device [=touch surface=] and normalized to [-1.0,1.0] where -1.0 is the leftmost coordinate and 1.0 is the rightmost coordinate.

        `position[0] = (2.0 * touchData.x / surfaceDimensions[0]) - 1`

      7. |position|[1] should be set to the device Y coordinate relative to the device [=touch surface=] and normalized to [-1.0,1.0] where -1.0 is the topmost coordinate and 1.0 is the bottommost coordinate.

        `position[1] = (2.0 * touchData.y / surfaceDimensions[1]) - 1`

    4. Set |touchEvent|.{{GamepadTouch/position}} to be |position:Float32Array|.
    5. Add |touchEvent| to {{Gamepad}}.{{Gamepad/[[touchEvents]]}}.
  4. Increment |surfaceId|
  5. Increment |surfaceId|

Constructing a `Gamepad`

This section supplements the Constructing a `Gamepad` section of the main Gamepad specification.

In addtion to the steps defined in the main Gamepad specification. When constructing a new `Gamepad` representing a connected gamepad device perform the following steps:

  1. Let |gamepad:Gamepad| be a newly created {{Gamepad}} instance:
    1. If the |gamepad| has touch surfaces, initialize |gamepad|'s {{Gamepad/touchEvents}} to an empty [=list=].
    2. Otherwise, initialize |gamepad|'s {{Gamepad/touchEvents}} null.

Partial GamepadHapticActuator Interface

This partial interface supplements the {{GamepadHapticActuator}} interface described in the main Gamepad spec.

        [Exposed=Window]
        partial interface GamepadHapticActuator {
          Promise<boolean> pulse(double value, double duration);
        };
      
pulse() method

{{GamepadHapticActuator/pulse()}} applies a |value:double| to the actuator for duration milliseconds. The value passed to pulse() is clamped to limits defined by the actuator type. The returned Promise will resolve true once the pulse has completed.

Repeated calls to pulse() override the previous values.

Glossary

touch surface is a surface that can detect contact from a users fingers and report where on the surface the contact is made.

touch surface enumeration order is an ordered listing of all the surfaces in a |gamepad|.

active touch point is defined in the Touch Events - Level 2 specification.

  翻译: