From 74a77666b9676057822f26e4b3a494197ab6e8fc Mon Sep 17 00:00:00 2001 From: staphen Date: Fri, 24 Dec 2021 16:10:24 -0500 Subject: [PATCH] Improve behavior of ToControllerButtonEvent() --- Source/DiabloUI/credits.cpp | 3 ++- Source/DiabloUI/diabloui.cpp | 3 ++- Source/DiabloUI/dialogs.cpp | 3 ++- Source/DiabloUI/progress.cpp | 3 ++- Source/DiabloUI/title.cpp | 3 ++- Source/controls/controller.cpp | 10 ++++++++++ Source/controls/controller.h | 5 +++-- Source/controls/devices/game_controller.cpp | 14 ++++++++++---- Source/controls/devices/game_controller.h | 7 +++++-- Source/controls/input.h | 17 +++++++++++++++++ Source/miniwin/misc_msg.cpp | 3 ++- 11 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 Source/controls/input.h diff --git a/Source/DiabloUI/credits.cpp b/Source/DiabloUI/credits.cpp index 771f8c23e..9ff2027f0 100644 --- a/Source/DiabloUI/credits.cpp +++ b/Source/DiabloUI/credits.cpp @@ -8,6 +8,7 @@ #include "DiabloUI/diabloui.h" #include "DiabloUI/support_lines.h" #include "control.h" +#include "controls/input.h" #include "controls/menu_controls.h" #include "engine/render/text_render.hpp" #include "hwcursor.hpp" @@ -138,7 +139,7 @@ bool TextDialog(char const *const *text, std::size_t textLines) do { creditsRenderer.Render(); UiFadeIn(); - while (SDL_PollEvent(&event) != 0) { + while (PollEvent(&event) != 0) { switch (event.type) { case SDL_KEYDOWN: case SDL_MOUSEBUTTONDOWN: diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index 856f0002b..19589d06c 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/Source/DiabloUI/diabloui.cpp @@ -13,6 +13,7 @@ #include "DiabloUI/dialogs.h" #include "DiabloUI/scrollbar.h" #include "controls/controller.h" +#include "controls/input.h" #include "controls/menu_controls.h" #include "discord/discord.h" #include "dx.h" @@ -748,7 +749,7 @@ void UiClearScreen() void UiPollAndRender(std::function eventHandler) { SDL_Event event; - while (SDL_PollEvent(&event) != 0) { + while (PollEvent(&event) != 0) { if (eventHandler && eventHandler(event)) continue; UiFocusNavigation(&event); diff --git a/Source/DiabloUI/dialogs.cpp b/Source/DiabloUI/dialogs.cpp index 266bed0ee..77835af39 100644 --- a/Source/DiabloUI/dialogs.cpp +++ b/Source/DiabloUI/dialogs.cpp @@ -6,6 +6,7 @@ #include "DiabloUI/diabloui.h" #include "DiabloUI/errorart.h" #include "control.h" +#include "controls/input.h" #include "controls/menu_controls.h" #include "dx.h" #include "hwcursor.hpp" @@ -220,7 +221,7 @@ void DialogLoop(const std::vector> &items, const std SDL_Event event; dialogEnd = false; do { - while (SDL_PollEvent(&event) != 0) { + while (PollEvent(&event) != 0) { switch (event.type) { case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: diff --git a/Source/DiabloUI/progress.cpp b/Source/DiabloUI/progress.cpp index 0439fba39..58d6a1e03 100644 --- a/Source/DiabloUI/progress.cpp +++ b/Source/DiabloUI/progress.cpp @@ -2,6 +2,7 @@ #include "DiabloUI/button.h" #include "DiabloUI/diabloui.h" #include "control.h" +#include "controls/input.h" #include "controls/menu_controls.h" #include "dx.h" #include "hwcursor.hpp" @@ -78,7 +79,7 @@ bool UiProgressDialog(const char *msg, int (*fnfunc)()) DrawMouse(); RenderPresent(); - while (SDL_PollEvent(&event) != 0) { + while (PollEvent(&event) != 0) { switch (event.type) { case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: diff --git a/Source/DiabloUI/title.cpp b/Source/DiabloUI/title.cpp index 1c306b7f9..95379a7e0 100644 --- a/Source/DiabloUI/title.cpp +++ b/Source/DiabloUI/title.cpp @@ -1,5 +1,6 @@ #include "DiabloUI/diabloui.h" #include "control.h" +#include "controls/input.h" #include "controls/menu_controls.h" #include "discord/discord.h" #include "utils/language.h" @@ -56,7 +57,7 @@ void UiTitleDialog() discord_manager::UpdateMenu(); - while (SDL_PollEvent(&event) != 0) { + while (PollEvent(&event) != 0) { if (GetMenuAction(event) != MenuAction_NONE) { endMenu = true; break; diff --git a/Source/controls/controller.cpp b/Source/controls/controller.cpp index c2ac4c284..52db9c1d0 100644 --- a/Source/controls/controller.cpp +++ b/Source/controls/controller.cpp @@ -8,6 +8,16 @@ namespace devilution { +void UnlockControllerState(const SDL_Event &event) +{ +#ifndef USE_SDL1 + GameController *const controller = GameController::Get(event); + if (controller != nullptr) { + controller->UnlockTriggerState(); + } +#endif +} + ControllerButtonEvent ToControllerButtonEvent(const SDL_Event &event) { ControllerButtonEvent result { ControllerButton_NONE, false }; diff --git a/Source/controls/controller.h b/Source/controls/controller.h index 8d50d353d..8186a16fe 100644 --- a/Source/controls/controller.h +++ b/Source/controls/controller.h @@ -11,8 +11,9 @@ struct ControllerButtonEvent { bool up; }; -// NOTE: Not idempotent because of how it handles axis triggers. -// Must be called exactly once per SDL input event. +// Must be called exactly once at the start of each SDL input event. +void UnlockControllerState(const SDL_Event &event); + ControllerButtonEvent ToControllerButtonEvent(const SDL_Event &event); bool IsControllerButtonPressed(ControllerButton button); diff --git a/Source/controls/devices/game_controller.cpp b/Source/controls/devices/game_controller.cpp index 3a4e5813d..dc76674cd 100644 --- a/Source/controls/devices/game_controller.cpp +++ b/Source/controls/devices/game_controller.cpp @@ -18,6 +18,12 @@ extern bool sgbControllerActive; std::vector GameController::controllers_; +void GameController::UnlockTriggerState() +{ + trigger_left_state_ = ControllerButton_NONE; + trigger_right_state_ = ControllerButton_NONE; +} + ControllerButton GameController::ToControllerButton(const SDL_Event &event) { switch (event.type) { @@ -29,18 +35,18 @@ ControllerButton GameController::ToControllerButton(const SDL_Event &event) } if (event.caxis.value > 16384 && !trigger_left_is_down_) { // 50% pressed trigger_left_is_down_ = true; - return ControllerButton_AXIS_TRIGGERLEFT; + trigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT; } - return ControllerButton_NONE; + return trigger_left_state_; case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: if (event.caxis.value < 8192) { // 25% pressed trigger_right_is_down_ = false; } if (event.caxis.value > 16384 && !trigger_right_is_down_) { // 50% pressed trigger_right_is_down_ = true; - return ControllerButton_AXIS_TRIGGERRIGHT; + trigger_right_state_ = ControllerButton_AXIS_TRIGGERRIGHT; } - return ControllerButton_NONE; + return trigger_right_state_; } break; case SDL_CONTROLLERBUTTONDOWN: diff --git a/Source/controls/devices/game_controller.h b/Source/controls/devices/game_controller.h index 5bc7bcf41..cdefe920d 100644 --- a/Source/controls/devices/game_controller.h +++ b/Source/controls/devices/game_controller.h @@ -21,8 +21,9 @@ public: static const std::vector &All(); static bool IsPressedOnAnyController(ControllerButton button); - // NOTE: Not idempotent. - // Must be called exactly once for each SDL input event. + // Must be called exactly once at the start of each SDL input event. + void UnlockTriggerState(); + ControllerButton ToControllerButton(const SDL_Event &event); bool IsPressed(ControllerButton button) const; @@ -34,6 +35,8 @@ private: SDL_GameController *sdl_game_controller_ = NULL; SDL_JoystickID instance_id_ = -1; + ControllerButton trigger_left_state_ = ControllerButton_NONE; + ControllerButton trigger_right_state_ = ControllerButton_NONE; bool trigger_left_is_down_ = false; bool trigger_right_is_down_ = false; }; diff --git a/Source/controls/input.h b/Source/controls/input.h new file mode 100644 index 000000000..0e4b728b8 --- /dev/null +++ b/Source/controls/input.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "controls/controller.h" + +namespace devilution { + +inline int PollEvent(SDL_Event *event) +{ + int result = SDL_PollEvent(event); + if (result != 0) + UnlockControllerState(*event); + return result; +} + +} // namespace devilution diff --git a/Source/miniwin/misc_msg.cpp b/Source/miniwin/misc_msg.cpp index dc1c8abe7..5ad08b06b 100644 --- a/Source/miniwin/misc_msg.cpp +++ b/Source/miniwin/misc_msg.cpp @@ -13,6 +13,7 @@ #include "controls/controller.h" #include "controls/controller_motion.h" #include "controls/game_controls.h" +#include "controls/input.h" #include "controls/plrctrls.h" #include "controls/remap_keyboard.h" #include "controls/touch/event_handlers.h" @@ -310,7 +311,7 @@ bool FetchMessage_Real(tagMSG *lpMsg) } SDL_Event e; - if (SDL_PollEvent(&e) == 0) { + if (PollEvent(&e) == 0) { return false; }