Input Sniffer, Overlays, and Tiles

Overview

ControllerHawk has at its foundation an EngineSubsystem called UInputSnifferSubsystem. It listens for key and mouse events as well as creates representations for devices attached to the current machine. Included in the plugin are a set of widgets (UI_ControllerTile and EUW_ControllerDebugger) which listen to sniffed events and attached devices to show live controller debug information.

InputSnifferSubsystem connects to Tile Widgets

The InputSniffer forwards events and creates representations of controllers that are used for visualizing user inputs.

As devices (i.e. specific controller hardware) are discovered they are captured as a USniffedInputDevice. These are then mapped to Controller Tiles and allow live updates based on key and analog events and the specific controller product information.

_images/sys_arch_UI_ControllerTile.png

The Controller Tile can switch specific representations based on the configured device or live inputs.

The Controller Tile (UControllerTileWidget) consists of several overlays (UControllerOverlayWidget) mapped to specific controller models or controller archetypes.

_images/sys_tool_EUW_ControllerDebugger.png

The Controller Debugger with an XBox and PS5 controller attached to the current machine.

To view which controllers are connected, run EUW_ControllerDebugger to see which controllers are connected and see live inputs.

Input Scopes

The InputSniffer uses InputScopes to try and gain additional information about connected devices and as it routes inputs.

_images/flow_xinput.png

The XInput flow uses Unreal’s XInput driver and we capture information using what is provided by that implementation.

For XInput, we use the FInputDeviceScope to capture information about the device as well as call an XInput function to retrieve product-specific information about the connected device.

_images/flow_hid.png

The HID flow uses a controller driver setup specific to ControllerHawk to capture more information about the underlying controller.

For ControllerHawk’s HID driver, we provide an additional scope FGameControllerScope which provides direct access to the interface (HID) and the specific controller implementation (IGameControllerInterface).

These scopes help us identify which devices particular input belongs to and lets us route this correctly to the Controller Tile assigned for that device. This information is captured in the FScopedInputDeviceHandle structure and reflected in the USniffedInputDevice, which passed to the Overlay and Tile.

Overlays

Each specific kind of controller is captured as an Overlay (UControllerOverlayWidget). Here is an example looking through the XInput (Xbox controller) overlay.

_images/overlay_xinput_widget.png

An XInput (Xbox controller) overlay

The overlay is a sandwich of a base Material followed by a series of textures arranged on a canvas.

  • The material is responsible for handling the highlight odd-shaped and variable buttons like the shoulder and triggers. Those button states are encoded and then sent to the material.

  • The textures are mostly just Kenney icons overlapped on each other / swapped out dynamically as the user presses inputs.

_images/overlay_xinput_structure.png

Structure of the XInput overlay

Overlays are mostly just data and widgets connected together that automatically respond to inputs. The Control Change Descriptions field is used to describe what happens to bound widgets as the user presses inputs. We bind the widget to an input event, and then the Control Change Description modifies the widget automatically.

_images/overlay_xinput_controlchanges.png

Example of a widget being bound to a control change description

Tiles

Tiles are used to manage the display of a specific controller. As mentioned above, UI_ControllerTile collects the available overlays into a switched display. It can be told to display a specific controller archetype using PresentControllerType() and show only inputs from a specific device by calling AssignDeviceHandle(). If no device handle is assigned then the tile forwards all events to the current overlay.

_images/sys_arch_UI_ControllerTile.png

If you want a Controller Tile that automatically switches to the active device, use UI_DynamicControllerTile. As you enter inputs, it will automatically switch to an available overlay.

_images/dynamic_controller_tile.gif