InputSource: Support querying current values

pull/3508/head
Stenzek 2 months ago
parent 5bdcde76ab
commit 33b3a6efda
No known key found for this signature in database

@ -8,6 +8,7 @@
#include "platform_misc.h"
#include "common/assert.h"
#include "common/bitutils.h"
#include "common/error.h"
#include "common/log.h"
#include "common/string_util.h"
@ -511,6 +512,45 @@ void DInputSource::CheckForStateChanges(size_t index, const DIJOYSTATE& new_stat
}
}
std::optional<float> DInputSource::GetCurrentValue(InputBindingKey key)
{
std::optional<float> ret;
if (key.source_type != InputSourceType::DInput)
return ret;
if (key.source_index >= m_controllers.size())
return ret;
const ControllerData& cd = m_controllers[key.source_index];
if (key.source_subtype == InputSubclass::ControllerAxis && key.data < cd.axis_offsets.size())
{
LONG value;
std::memcpy(&value, reinterpret_cast<const u8*>(&cd.last_state) + cd.axis_offsets[key.data], sizeof(value));
ret = static_cast<float>(value) / (value < 0 ? 32768.0f : 32767.0f);
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
if (key.data < cd.num_buttons)
{
ret = BoolToFloat(cd.last_state.rgbButtons[key.data]);
}
else
{
// might be a hat
const u32 hat_index = (key.data - cd.num_buttons) / NUM_HAT_DIRECTIONS;
const u32 hat_direction = (key.data - cd.num_buttons) % NUM_HAT_DIRECTIONS;
if (hat_index < cd.num_hats)
{
const std::array<bool, NUM_HAT_DIRECTIONS> buttons(GetHatButtons(cd.last_state.rgdwPOV[hat_index]));
ret = BoolToFloat(buttons[hat_direction]);
}
}
}
return ret;
}
std::unique_ptr<InputSource> InputSource::CreateDInputSource()
{
return std::make_unique<DInputSource>();

@ -39,6 +39,7 @@ public:
void Shutdown() override;
void PollEvents() override;
std::optional<float> GetCurrentValue(InputBindingKey key) override;
InputManager::DeviceList EnumerateDevices() override;
InputManager::VibrationMotorList EnumerateVibrationMotors(std::optional<InputBindingKey> for_device) override;
bool GetGenericBindingMapping(std::string_view device, GenericInputBindingMapping* mapping) override;

@ -25,16 +25,34 @@ public:
InputSource();
virtual ~InputSource();
// Sets up the input source.
virtual bool Initialize(const SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock) = 0;
/// Updates the settings for this input source. This should be called when settings change.
virtual void UpdateSettings(const SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock) = 0;
/// Reloads the devices for this input source. This should be called when a device change is detected.
virtual bool ReloadDevices() = 0;
/// Shuts down the input source, releasing any resources it holds.
virtual void Shutdown() = 0;
/// Polls the input source for events. This should be called at a regular interval, such as every frame.
virtual void PollEvents() = 0;
/// Returns the current value for the specified device and key.
virtual std::optional<float> GetCurrentValue(InputBindingKey key) = 0;
/// Returns true if the source contains the specified device.
virtual bool ContainsDevice(std::string_view device) const = 0;
/// Parses a key string for the specified device. Returns std::nullopt if the key is not valid.
virtual std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) = 0;
/// Converts a key to a string representation. The string should be suitable for parsing with ParseKeyString().
virtual TinyString ConvertKeyToString(InputBindingKey key) = 0;
/// Converts a key to an icon representation. The icon is suitable for display in the UI.
virtual TinyString ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper) = 0;
/// Enumerates available devices. Returns a pair of the prefix (e.g. SDL-0) and the device name.

@ -1145,6 +1145,46 @@ bool SDLInputSource::HandleJoystickHatEvent(const SDL_JoyHatEvent* ev)
return true;
}
std::optional<float> SDLInputSource::GetCurrentValue(InputBindingKey key)
{
std::optional<float> ret;
if (key.source_type != InputSourceType::SDL)
return ret;
const auto cd = GetControllerDataForPlayerId(static_cast<int>(key.source_index));
if (cd == m_controllers.end())
return ret;
if (key.source_subtype == InputSubclass::ControllerAxis)
{
if (cd->gamepad && key.data < std::size(s_sdl_axis_names))
ret = NormalizeS16(SDL_GetGamepadAxis(cd->gamepad, static_cast<SDL_GamepadAxis>(key.data)));
else if (key.data >= std::size(s_sdl_axis_names))
ret = NormalizeS16(SDL_GetJoystickAxis(cd->joystick, static_cast<int>(key.data - std::size(s_sdl_axis_names))));
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
if (cd->gamepad && key.data < std::size(s_sdl_button_names))
{
ret = BoolToFloat(SDL_GetGamepadButton(cd->gamepad, static_cast<SDL_GamepadButton>(key.data)));
}
else if (key.data >= std::size(s_sdl_axis_names))
{
ret =
BoolToFloat(SDL_GetJoystickButton(cd->joystick, static_cast<int>(key.data - std::size(s_sdl_button_names))));
}
}
else if (key.source_subtype == InputSubclass::ControllerHat)
{
const u32 hat_index = key.data / static_cast<u32>(std::size(s_sdl_hat_direction_names));
const u8 hat_direction = Truncate8(key.data % static_cast<u32>(std::size(s_sdl_hat_direction_names)));
const u8 hat_value = SDL_GetJoystickHat(cd->joystick, static_cast<int>(hat_index));
ret = BoolToFloat((hat_value & (1u << hat_direction)) != 0);
}
return ret;
}
InputManager::VibrationMotorList SDLInputSource::EnumerateVibrationMotors(std::optional<InputBindingKey> for_device)
{
InputManager::VibrationMotorList ret;

@ -30,6 +30,7 @@ public:
void Shutdown() override;
void PollEvents() override;
std::optional<float> GetCurrentValue(InputBindingKey key) override;
InputManager::DeviceList EnumerateDevices() override;
InputManager::VibrationMotorList EnumerateVibrationMotors(std::optional<InputBindingKey> for_device) override;
bool GetGenericBindingMapping(std::string_view device, GenericInputBindingMapping* mapping) override;

@ -76,6 +76,12 @@ void Win32RawInputSource::PollEvents()
// noop, handled by message pump
}
std::optional<float> Win32RawInputSource::GetCurrentValue(InputBindingKey key)
{
// not really used
return std::nullopt;
}
InputManager::DeviceList Win32RawInputSource::EnumerateDevices()
{
InputManager::DeviceList ret;

@ -26,6 +26,7 @@ public:
void Shutdown() override;
void PollEvents() override;
std::optional<float> GetCurrentValue(InputBindingKey key) override;
InputManager::DeviceList EnumerateDevices() override;
InputManager::VibrationMotorList EnumerateVibrationMotors(std::optional<InputBindingKey> for_device) override;
bool GetGenericBindingMapping(std::string_view device, GenericInputBindingMapping* mapping) override;

@ -508,6 +508,44 @@ void XInputSource::CheckForStateChanges(u32 index, const XINPUT_STATE& new_state
cd.last_state = new_state;
}
std::optional<float> XInputSource::GetCurrentValue(InputBindingKey key)
{
std::optional<float> ret;
if (key.source_type != InputSourceType::XInput || key.source_index >= NUM_CONTROLLERS)
return ret;
const ControllerData& cd = m_controllers[key.source_index];
if (!cd.connected)
return ret;
if (key.source_subtype == InputSubclass::ControllerAxis && key.data < NUM_AXES)
{
const XINPUT_GAMEPAD& state = cd.last_state.Gamepad;
#define CHECK_AXIS(field, axis, min_value, max_value) \
case axis: \
ret = static_cast<float>(state.field) / ((state.field < 0) ? min_value : max_value);
// Y axes is inverted in XInput when compared to SDL.
switch (key.data)
{
CHECK_AXIS(sThumbLX, AXIS_LEFTX, 32768, 32767);
CHECK_AXIS(sThumbLY, AXIS_LEFTY, -32768, -32767);
CHECK_AXIS(sThumbRX, AXIS_RIGHTX, 32768, 32767);
CHECK_AXIS(sThumbRY, AXIS_RIGHTY, -32768, -32767);
CHECK_AXIS(bLeftTrigger, AXIS_LEFTTRIGGER, 0, 255);
CHECK_AXIS(bRightTrigger, AXIS_RIGHTTRIGGER, 0, 255);
}
}
else if (key.source_subtype == InputSubclass::ControllerButton && key.data < NUM_BUTTONS)
{
const XINPUT_GAMEPAD& state = cd.last_state.Gamepad;
const u16 button_mask = s_button_masks[key.data];
ret = BoolToFloat((state.wButtons & button_mask) != 0);
}
return ret;
}
void XInputSource::UpdateMotorState(InputBindingKey key, float intensity)
{
if (key.source_subtype != InputSubclass::ControllerMotor || key.source_index >= NUM_CONTROLLERS)

@ -41,6 +41,7 @@ public:
void Shutdown() override;
void PollEvents() override;
std::optional<float> GetCurrentValue(InputBindingKey key) override;
InputManager::DeviceList EnumerateDevices() override;
InputManager::VibrationMotorList EnumerateVibrationMotors(std::optional<InputBindingKey> for_device) override;
bool GetGenericBindingMapping(std::string_view device, GenericInputBindingMapping* mapping) override;

Loading…
Cancel
Save