Detecting input devices in Godot

One thing I really like in games is the little touches and one of those little touches is when the control prompts match up with the input device I'm using.

YouTube: Detecting input device
YouTube: Detecting the input device to show custom controller inputs.

I wanted that for my game so I set about working out how to do that in Godot and, as with most things in Godot, it turned out to be easier than I expected.

You just need a node that implements _input() and then to sniff out the event to see what it was.

I ended up with some code like this:

func _input(event: InputEvent) -> void:
    var next_device: String = device
    var next_device_index: int = device_index
    
    # Did we just press a key on the keyboard?
    if event is InputEventKey and event.is_pressed():
        next_device = DEVICE_KEYBOARD
        next_device_index = -1
    
    # Did we just use a gamepad?
    elif (event is InputEventJoypadButton and event.is_pressed()) \
        or (event is InputEventJoypadMotion and event.axis_value > 0.1):
        next_device = get_simplified_device_name(Input.get_joy_name(event.device))
        next_device_index = event.device

    if next_device != device or next_device_index != device_index:
        device = next_device
        device_index = next_device_index
        emit_signal("device_changed", device, device_index)

So, if the last input was from a key being pressed we respond with "keyboard" as the active device.

If the last input was from a gamepad then we look at what Godot thinks the name of the game pad is.

I do a bit of tidying here on the actual device name to simplify which textures I need to load.

If the device has changed since last time then I emit a "device_changed" signal to notify my indicators.

Then, in the indicator, I can swap out which texture is showing as the input (I have some smarts in there to guess which actual key or button is mapped to the given action that I'm indicating).

func _on_input_device_changed(device: String, _device_index: int) -> void:
    keyboard.visible = device == InputHelper.DEVICE_KEYBOARD
    gamepad.visible = !keyboard.visible

    match action:
        Actions.Action:
            key_label.text = InputHelper.get_key_label("ui_accept")
            gamepad_sprite.texture = get_button_texture("ui_accept")
        
        Actions.Inventory:
            key_label.text = InputHelper.get_key_label("ui_inventory")
            gamepad_sprite.texture = get_button_texture("ui_inventory")

I figured this input helper might be useful to other Godot devs so I've open sourced it as a Godot addon.

Give it a go and let me know what you think.