Gamepad Support

Gameface can receive and process input data from one or more gamepad devices. Cohtml supports the W3C standard for gamepads. However, previous versions of the software diverged from the standard in several significant ways which are described further down on this page.

Adding a gamepad controller

The current gamepad indexing interface for Gameface follows the guidelines described by the W3C standard for gamepad support. Registering a new gamepad is achieved through the RegisterGamepad function, which takes several different attributes:

RegisterGamepad(unsigned id, const char* info, unsigned axesCount, unsigned buttonsCount, void* reserved = nullptr)
  • @param id serves as the unique identifier for the gamepad.
  • @param info contains general information for the gamepad.
  • @param axesCount specifies the number of analog axes on the gamepad.
  • @param buttonsCount specifies the number of buttons on the gamepad.
  • @param reserved is a reserved parameter that must be set to nullptr.

Updating and removing controllers

After adding a gamepad, you must call the function UpdateGamepad at regular intervals to pass the state of the gamepad to Gameface. This function is used to communicate with Cohtml which buttons are pressed, and how the thumbsticks have been manipulated.

virtual void UpdateGamepadState(const cohtml::GamepadState& state) = 0;
  • @param state specifies the new state of the gamepad. It should contain the ID of the gamepad to update, a timestamp, and the new values for the axes/buttons.

Removing gamepads is done by calling UnregisterGamepad.

virtual void UnregisterGamepad(unsigned id) = 0;
  • @param id specifies the id of the gamepad you want to unregister

Gamepad IDs on the C++ side

Each gamepad must always have exactly one unique ID, which should stay consistent throughout the calls to RegisterGamepad, UnregisterGamepad and UpdateGamepadState. You can set any value for each gamepad, as long as you keep those values unique and consistent.

Differences between versions

Different versions of Gameface handle gamepad support differently. Older versions of the software diverge from the W3C, specifically when it comes to indexing gamepads.

Gameface 1.3.1 and earlier

Removing the gamepad element also removes the index of the element within the collection. This reduces the size of the collection.

If a gamepad is removed, then added again, it will be registered under a new index in the collection. Unregistering a gamepad removes the gamepad element from the collection. This reduces the size of the collection and therefore rightmost indices that are saved and used in JavaScript might get invalidated.

Gameface 1.3.2 to 1.4.2

Removing the controller does not remove the respective element from the gamepad collection. Instead, it sets the element to null. If the same controller is reconnected, it will be assigned the same index it was initially given.

Gameface 1.4.2 and newer

From version 1.4.2 onward, Gameface handles gamepad indexing according to the guidelines detailed in the W3C standard. The id values that are passed to System::RegisterGamepad are kept as separate values from the gamepad indices.

Whenever a gamepad is connected, it will be assigned to the first free index, starting from 0. Indices are assigned based on a first-come, first-serve principle, starting at zero. If a gamepad is disconnected, the now available index is not reassigned to gamepads that are still connected. New connected or reconnected gamepads are assigned to the leftmost available slot in the gamepad collection or pushed at its back.

When a gamepad is unregistered, previously assigned indices are not reassigned to gamepads that continue to be connected. However, if the same or a new gamepad is connected, the lowest available index will be used.