From 6e18e56089c5379e832d42834621ee2a402b6e91 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 15 Dec 2019 00:31:07 +1000 Subject: [PATCH] Controller: Support general axis input events --- src/core/controller.cpp | 20 ++++++++++++++++ src/core/controller.h | 9 ++++++++ src/core/digital_controller.cpp | 12 ++++++++++ src/core/digital_controller.h | 8 +++++-- src/duckstation/sdl_host_interface.cpp | 32 +++++++++++++++++++++----- src/duckstation/sdl_host_interface.h | 1 + 6 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/core/controller.cpp b/src/core/controller.cpp index cea5792a4..34964dc95 100644 --- a/src/core/controller.cpp +++ b/src/core/controller.cpp @@ -21,6 +21,8 @@ bool Controller::Transfer(const u8 data_in, u8* data_out) return false; } +void Controller::SetAxisState(s32 axis_code, float value) {} + void Controller::SetButtonState(s32 button_code, bool pressed) {} std::unique_ptr Controller::Create(ControllerType type) @@ -38,6 +40,24 @@ std::unique_ptr Controller::Create(ControllerType type) } } +std::optional Controller::GetAxisCodeByName(std::string_view button_name) const +{ + return std::nullopt; +} + +std::optional Controller::GetAxisCodeByName(ControllerType type, std::string_view axis_name) +{ + switch (type) + { + case ControllerType::DigitalController: + return DigitalController::StaticGetAxisCodeByName(axis_name); + + case ControllerType::None: + default: + return std::nullopt; + } +} + std::optional Controller::GetButtonCodeByName(ControllerType type, std::string_view button_name) { switch (type) diff --git a/src/core/controller.h b/src/core/controller.h index 56c66c49b..5aea0c3dc 100644 --- a/src/core/controller.h +++ b/src/core/controller.h @@ -15,6 +15,9 @@ public: /// Returns the type of controller. virtual ControllerType GetType() const = 0; + /// Gets the integer code for an axis in the specified controller type. + virtual std::optional GetAxisCodeByName(std::string_view axis_name) const; + /// Gets the integer code for a button in the specified controller type. virtual std::optional GetButtonCodeByName(std::string_view button_name) const; @@ -27,12 +30,18 @@ public: // Returns the value of ACK, as well as filling out_data. virtual bool Transfer(const u8 data_in, u8* data_out); + /// Changes the specified axis state. Values are normalized from -1..1. + virtual void SetAxisState(s32 axis_code, float value); + /// Changes the specified button state. virtual void SetButtonState(s32 button_code, bool pressed); /// Creates a new controller of the specified type. static std::unique_ptr Create(ControllerType type); + /// Gets the integer code for an axis in the specified controller type. + static std::optional GetAxisCodeByName(ControllerType type, std::string_view axis_name); + /// Gets the integer code for a button in the specified controller type. static std::optional GetButtonCodeByName(ControllerType type, std::string_view button_name); }; diff --git a/src/core/digital_controller.cpp b/src/core/digital_controller.cpp index 5509039f5..b4252810f 100644 --- a/src/core/digital_controller.cpp +++ b/src/core/digital_controller.cpp @@ -11,11 +11,18 @@ ControllerType DigitalController::GetType() const return ControllerType::DigitalController; } +std::optional DigitalController::GetAxisCodeByName(std::string_view axis_name) const +{ + return StaticGetAxisCodeByName(axis_name); +} + std::optional DigitalController::GetButtonCodeByName(std::string_view button_name) const { return StaticGetButtonCodeByName(button_name); } +void DigitalController::SetAxisState(s32 axis_code, float value) {} + void DigitalController::SetButtonState(Button button, bool pressed) { if (pressed) @@ -91,6 +98,11 @@ std::unique_ptr DigitalController::Create() return std::make_unique(); } +std::optional DigitalController::StaticGetAxisCodeByName(std::string_view button_name) +{ + return std::nullopt; +} + std::optional DigitalController::StaticGetButtonCodeByName(std::string_view button_name) { #define BUTTON(name) \ diff --git a/src/core/digital_controller.h b/src/core/digital_controller.h index bd9ab7a8e..759905c62 100644 --- a/src/core/digital_controller.h +++ b/src/core/digital_controller.h @@ -32,17 +32,21 @@ public: ~DigitalController() override; static std::unique_ptr Create(); + static std::optional StaticGetAxisCodeByName(std::string_view button_name); static std::optional StaticGetButtonCodeByName(std::string_view button_name); ControllerType GetType() const override; + std::optional GetAxisCodeByName(std::string_view axis_name) const override; std::optional GetButtonCodeByName(std::string_view button_name) const override; - void SetButtonState(Button button, bool pressed); - void SetButtonState(s32 button_code, bool pressed); + void SetAxisState(s32 axis_code, float value) override; + void SetButtonState(s32 button_code, bool pressed) override; void ResetTransferState() override; bool Transfer(const u8 data_in, u8* data_out) override; + void SetButtonState(Button button, bool pressed); + private: enum class TransferState : u8 { diff --git a/src/duckstation/sdl_host_interface.cpp b/src/duckstation/sdl_host_interface.cpp index e95da0ef2..8de754076 100644 --- a/src/duckstation/sdl_host_interface.cpp +++ b/src/duckstation/sdl_host_interface.cpp @@ -459,7 +459,7 @@ void SDLHostInterface::UpdateKeyboardControllerMapping() { m_keyboard_button_mapping.fill(-1); - const Controller* controller = m_system->GetController(0); + const Controller* controller = m_system ? m_system->GetController(0) : nullptr; if (controller) { #define SET_BUTTON_MAP(action, name) \ @@ -490,7 +490,8 @@ bool SDLHostInterface::HandleSDLKeyEventForController(const SDL_Event* event) Controller* controller; #define DO_ACTION(action) \ - if ((controller = m_system->GetController(0)) != nullptr && m_keyboard_button_mapping[static_cast(action)]) \ + if ((controller = m_system ? m_system->GetController(0) : nullptr) != nullptr && \ + m_keyboard_button_mapping[static_cast(action)]) \ { \ controller->SetButtonState(m_keyboard_button_mapping[static_cast(action)], pressed); \ } @@ -563,13 +564,22 @@ bool SDLHostInterface::HandleSDLKeyEventForController(const SDL_Event* event) void SDLHostInterface::UpdateControllerControllerMapping() { + m_controller_axis_mapping.fill(-1); m_controller_button_mapping.fill(-1); - const Controller* controller = m_system->GetController(0); + Controller* controller = m_system ? m_system->GetController(0) : nullptr; if (controller) { -#define SET_BUTTON_MAP(action, name) \ - m_controller_button_mapping[static_cast(action)] = controller->GetButtonCodeByName(name).value_or(-1) +#define SET_AXIS_MAP(axis, name) m_controller_axis_mapping[axis] = controller->GetAxisCodeByName(name).value_or(-1) +#define SET_BUTTON_MAP(button, name) \ + m_controller_button_mapping[button] = controller->GetButtonCodeByName(name).value_or(-1) + + SET_AXIS_MAP(SDL_CONTROLLER_AXIS_LEFTX, "LeftX"); + SET_AXIS_MAP(SDL_CONTROLLER_AXIS_LEFTY, "LeftY"); + SET_AXIS_MAP(SDL_CONTROLLER_AXIS_RIGHTX, "RightX"); + SET_AXIS_MAP(SDL_CONTROLLER_AXIS_RIGHTY, "RightY"); + SET_AXIS_MAP(SDL_CONTROLLER_AXIS_TRIGGERLEFT, "LeftTrigger"); + SET_AXIS_MAP(SDL_CONTROLLER_AXIS_TRIGGERRIGHT, "RightTrigger"); SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_DPAD_UP, "Up"); SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_DPAD_DOWN, "Down"); @@ -586,6 +596,7 @@ void SDLHostInterface::UpdateControllerControllerMapping() SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_START, "Start"); SET_BUTTON_MAP(SDL_CONTROLLER_BUTTON_BACK, "Select"); +#undef SET_AXIS_MAP #undef SET_BUTTON_MAP } } @@ -593,10 +604,19 @@ void SDLHostInterface::UpdateControllerControllerMapping() void SDLHostInterface::HandleSDLControllerAxisEventForController(const SDL_Event* ev) { // Log_DevPrintf("axis %d %d", ev->caxis.axis, ev->caxis.value); - Controller* controller = m_system->GetController(0); + Controller* controller = m_system ? m_system->GetController(0) : nullptr; if (!controller) return; + // proper axis mapping + if (m_controller_axis_mapping[ev->caxis.axis] >= 0) + { + const float value = static_cast(ev->caxis.value) / (ev->caxis.value < 0 ? 32768.0f : 32767.0f); + controller->SetAxisState(m_controller_axis_mapping[ev->caxis.axis], value); + return; + } + + // axis-as-button mapping static constexpr int deadzone = 8192; const bool negative = (ev->caxis.value < 0); const bool active = (std::abs(ev->caxis.value) >= deadzone); diff --git a/src/duckstation/sdl_host_interface.h b/src/duckstation/sdl_host_interface.h index f908d0658..611cc6a7a 100644 --- a/src/duckstation/sdl_host_interface.h +++ b/src/duckstation/sdl_host_interface.h @@ -125,6 +125,7 @@ private: KeyboardControllerActionMap m_keyboard_button_mapping; std::map m_sdl_controllers; + std::array m_controller_axis_mapping; std::array m_controller_button_mapping; u32 m_switch_gpu_renderer_event_id = 0;