diff --git a/Source/controls/game_controls.cpp b/Source/controls/game_controls.cpp index db91eba64..6e0298494 100644 --- a/Source/controls/game_controls.cpp +++ b/Source/controls/game_controls.cpp @@ -11,8 +11,10 @@ #include "controls/plrctrls.h" #include "controls/touch/gamepad.h" #include "doom.h" +#include "gamemenu.h" #include "gmenu.h" #include "options.h" +#include "qol/stash.h" #include "stores.h" namespace devilution { @@ -103,36 +105,6 @@ SDL_Keycode TranslateControllerButtonToSpellbookKey(ControllerButton controllerB } } -} // namespace - -ControllerButton TranslateTo(GamepadLayout layout, ControllerButton button) -{ - if (layout != GamepadLayout::Nintendo) - return button; - - switch (button) { - case ControllerButton_BUTTON_A: - return ControllerButton_BUTTON_B; - case ControllerButton_BUTTON_B: - return ControllerButton_BUTTON_A; - case ControllerButton_BUTTON_X: - return ControllerButton_BUTTON_Y; - case ControllerButton_BUTTON_Y: - return ControllerButton_BUTTON_X; - default: - return button; - } -} - -bool SkipsMovie(ControllerButtonEvent ctrlEvent) -{ - return IsAnyOf(ctrlEvent.button, - ControllerButton_BUTTON_A, - ControllerButton_BUTTON_B, - ControllerButton_BUTTON_START, - ControllerButton_BUTTON_BACK); -} - bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrlEvent, GameAction *action) { const bool inGameMenu = InGameMenu(); @@ -241,6 +213,121 @@ bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrlEvent, Game return false; } +void PressControllerButton(ControllerButton button) +{ + if (IsStashOpen) { + switch (button) { + case ControllerButton_BUTTON_BACK: + StartGoldWithdraw(); + return; + case ControllerButton_BUTTON_LEFTSHOULDER: + Stash.PreviousPage(); + return; + case ControllerButton_BUTTON_RIGHTSHOULDER: + Stash.NextPage(); + return; + } + } + + if (PadHotspellMenuActive) { + auto quickSpellAction = [](size_t slot) { + if (spselflag) { + SetSpeedSpell(slot); + return; + } + if (!*sgOptions.Gameplay.quickCast) + ToggleSpell(slot); + else + QuickCast(slot); + }; + switch (button) { + case devilution::ControllerButton_BUTTON_A: + quickSpellAction(2); + return; + case devilution::ControllerButton_BUTTON_B: + quickSpellAction(3); + return; + case devilution::ControllerButton_BUTTON_X: + quickSpellAction(0); + return; + case devilution::ControllerButton_BUTTON_Y: + quickSpellAction(1); + return; + default: + break; + } + } + + if (PadMenuNavigatorActive) { + switch (button) { + case devilution::ControllerButton_BUTTON_DPAD_UP: + PressEscKey(); + LastMouseButtonAction = MouseActionType::None; + PadHotspellMenuActive = false; + PadMenuNavigatorActive = false; + gamemenu_on(); + return; + case devilution::ControllerButton_BUTTON_DPAD_DOWN: + DoAutoMap(); + return; + case devilution::ControllerButton_BUTTON_DPAD_LEFT: + ProcessGameAction(GameAction { GameActionType_TOGGLE_CHARACTER_INFO }); + return; + case devilution::ControllerButton_BUTTON_DPAD_RIGHT: + ProcessGameAction(GameAction { GameActionType_TOGGLE_INVENTORY }); + return; + case devilution::ControllerButton_BUTTON_A: + ProcessGameAction(GameAction { GameActionType_TOGGLE_SPELL_BOOK }); + return; + case devilution::ControllerButton_BUTTON_B: + return; + case devilution::ControllerButton_BUTTON_X: + ProcessGameAction(GameAction { GameActionType_TOGGLE_QUEST_LOG }); + return; + case devilution::ControllerButton_BUTTON_Y: +#ifdef __3DS__ + sgOptions.Graphics.zoom.SetValue(!*sgOptions.Graphics.zoom); + CalcViewportGeometry(); +#endif + return; + default: + break; + } + } + + sgOptions.Padmapper.ButtonPressed(button); +} + +} // namespace + +ControllerButton TranslateTo(GamepadLayout layout, ControllerButton button) +{ + if (layout != GamepadLayout::Nintendo) + return button; + + switch (button) { + case ControllerButton_BUTTON_A: + return ControllerButton_BUTTON_B; + case ControllerButton_BUTTON_B: + return ControllerButton_BUTTON_A; + case ControllerButton_BUTTON_X: + return ControllerButton_BUTTON_Y; + case ControllerButton_BUTTON_Y: + return ControllerButton_BUTTON_X; + default: + return button; + } +} + +bool SkipsMovie(ControllerButtonEvent ctrlEvent) +{ + return IsAnyOf(ctrlEvent.button, + ControllerButton_BUTTON_A, + ControllerButton_BUTTON_B, + ControllerButton_BUTTON_START, + ControllerButton_BUTTON_BACK); +} + bool IsSimulatedMouseClickBinding(ControllerButtonEvent ctrlEvent) { ControllerButtonCombo leftMouseClickBinding1 = sgOptions.Padmapper.ButtonComboForAction("LeftMouseClick1"); @@ -258,4 +345,33 @@ AxisDirection GetMoveDirection() return GetLeftStickOrDpadDirection(true); } +bool HandleControllerButtonEvent(const SDL_Event &event, GameAction &action) +{ + const ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event); + bool isGamepadMotion = ProcessControllerMotion(event, ctrlEvent); + DetectInputMethod(event, ctrlEvent); + if (isGamepadMotion) { + return true; + } + + if (ctrlEvent.button != ControllerButton_NONE && ctrlEvent.button == SuppressedButton) { + if (!ctrlEvent.up) + return true; + SuppressedButton = ControllerButton_NONE; + } + + if (GetGameAction(event, ctrlEvent, &action)) { + ProcessGameAction(action); + return true; + } else if (ctrlEvent.button != ControllerButton_NONE) { + if (!ctrlEvent.up) + PressControllerButton(ctrlEvent.button); + else + sgOptions.Padmapper.ButtonReleased(ctrlEvent.button); + return true; + } + + return false; +} + } // namespace devilution diff --git a/Source/controls/game_controls.h b/Source/controls/game_controls.h index 5c4c38911..309790788 100644 --- a/Source/controls/game_controls.h +++ b/Source/controls/game_controls.h @@ -62,12 +62,13 @@ struct GameAction { ControllerButton TranslateTo(GamepadLayout layout, ControllerButton button); bool SkipsMovie(ControllerButtonEvent ctrlEvent); -bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrlEvent, GameAction *action); bool IsSimulatedMouseClickBinding(ControllerButtonEvent ctrlEvent); AxisDirection GetMoveDirection(); +bool HandleControllerButtonEvent(const SDL_Event &event, GameAction &action); + extern bool PadMenuNavigatorActive; extern bool PadHotspellMenuActive; diff --git a/Source/diablo.cpp b/Source/diablo.cpp index fc772a855..c99f194ec 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -20,6 +20,7 @@ #endif #include "DiabloUI/diabloui.h" #include "controls/plrctrls.h" +#include "controls/remap_keyboard.h" #include "diablo.h" #include "discord/discord.h" #include "doom.h" @@ -415,8 +416,9 @@ void RightMouseDown(bool isShiftHeld) } } -void ReleaseKey(int vkey) +void ReleaseKey(SDL_Keycode vkey) { + remap_keyboard_key(&vkey); if (sgnTimeoutCurs != CURSOR_NONE || dropGoldFlag) return; sgOptions.Keymapper.KeyReleased(vkey); @@ -439,6 +441,8 @@ void ClosePanels() void PressKey(SDL_Keycode vkey, uint16_t modState) { + remap_keyboard_key(&vkey); + if (vkey == SDLK_UNKNOWN) return; @@ -597,93 +601,60 @@ void PressKey(SDL_Keycode vkey, uint16_t modState) } } -void PressControllerButton(ControllerButton button) +void HandleMouseButtonDown(Uint8 button, uint16_t modState) { - if (IsStashOpen) { + if (sgbMouseDown == CLICK_NONE) { switch (button) { - case ControllerButton_BUTTON_BACK: - StartGoldWithdraw(); - return; - case ControllerButton_BUTTON_LEFTSHOULDER: - Stash.PreviousPage(); - return; - case ControllerButton_BUTTON_RIGHTSHOULDER: - Stash.NextPage(); - return; - } - } - - if (PadHotspellMenuActive) { - auto quickSpellAction = [](size_t slot) { - if (spselflag) { - SetSpeedSpell(slot); - return; - } - if (!*sgOptions.Gameplay.quickCast) - ToggleSpell(slot); - else - QuickCast(slot); - }; - switch (button) { - case devilution::ControllerButton_BUTTON_A: - quickSpellAction(2); - return; - case devilution::ControllerButton_BUTTON_B: - quickSpellAction(3); - return; - case devilution::ControllerButton_BUTTON_X: - quickSpellAction(0); - return; - case devilution::ControllerButton_BUTTON_Y: - quickSpellAction(1); - return; - default: + case SDL_BUTTON_LEFT: + sgbMouseDown = CLICK_LEFT; + LeftMouseDown(modState); + break; + case SDL_BUTTON_RIGHT: + sgbMouseDown = CLICK_RIGHT; + RightMouseDown((modState & KMOD_SHIFT) != 0); break; - } - } - - if (PadMenuNavigatorActive) { - switch (button) { - case devilution::ControllerButton_BUTTON_DPAD_UP: - PressEscKey(); - LastMouseButtonAction = MouseActionType::None; - PadHotspellMenuActive = false; - PadMenuNavigatorActive = false; - gamemenu_on(); - return; - case devilution::ControllerButton_BUTTON_DPAD_DOWN: - DoAutoMap(); - return; - case devilution::ControllerButton_BUTTON_DPAD_LEFT: - ProcessGameAction(GameAction { GameActionType_TOGGLE_CHARACTER_INFO }); - return; - case devilution::ControllerButton_BUTTON_DPAD_RIGHT: - ProcessGameAction(GameAction { GameActionType_TOGGLE_INVENTORY }); - return; - case devilution::ControllerButton_BUTTON_A: - ProcessGameAction(GameAction { GameActionType_TOGGLE_SPELL_BOOK }); - return; - case devilution::ControllerButton_BUTTON_B: - return; - case devilution::ControllerButton_BUTTON_X: - ProcessGameAction(GameAction { GameActionType_TOGGLE_QUEST_LOG }); - return; - case devilution::ControllerButton_BUTTON_Y: -#ifdef __3DS__ - sgOptions.Graphics.zoom.SetValue(!*sgOptions.Graphics.zoom); - CalcViewportGeometry(); -#endif - return; default: + sgOptions.Keymapper.KeyPressed(button | KeymapperMouseButtonMask); break; } } +} - sgOptions.Padmapper.ButtonPressed(button); +void HandleMouseButtonUp(Uint8 button, uint16_t modState) +{ + if (sgbMouseDown == CLICK_LEFT && button == SDL_BUTTON_LEFT) { + LastMouseButtonAction = MouseActionType::None; + sgbMouseDown = CLICK_NONE; + LeftMouseUp(modState); + } else if (sgbMouseDown == CLICK_RIGHT && button == SDL_BUTTON_RIGHT) { + LastMouseButtonAction = MouseActionType::None; + sgbMouseDown = CLICK_NONE; + } else { + sgOptions.Keymapper.KeyReleased(button | KeymapperMouseButtonMask); + } } void GameEventHandler(const SDL_Event &event, uint16_t modState) { + GameAction action; + if (HandleControllerButtonEvent(event, action)) { + if (action.type == GameActionType_SEND_KEY) { + if ((action.send_key.vk_code & KeymapperMouseButtonMask) != 0) { + const unsigned button = action.send_key.vk_code & ~KeymapperMouseButtonMask; + if (!action.send_key.up) + HandleMouseButtonDown(static_cast(button), modState); + else + HandleMouseButtonUp(static_cast(button), modState); + } else { + if (!action.send_key.up) + PressKey(static_cast(action.send_key.vk_code), modState); + else + ReleaseKey(static_cast(action.send_key.vk_code)); + } + } + return; + } + switch (event.type) { case SDL_KEYDOWN: PressKey(event.key.keysym.sym, modState); @@ -697,41 +668,11 @@ void GameEventHandler(const SDL_Event &event, uint16_t modState) return; case SDL_MOUSEBUTTONDOWN: MousePosition = { event.button.x, event.button.y }; - if (sgbMouseDown == CLICK_NONE) { - switch (event.button.button) { - case SDL_BUTTON_LEFT: - sgbMouseDown = CLICK_LEFT; - LeftMouseDown(modState); - break; - case SDL_BUTTON_RIGHT: - sgbMouseDown = CLICK_RIGHT; - RightMouseDown((modState & KMOD_SHIFT) != 0); - break; - default: - sgOptions.Keymapper.KeyPressed(event.button.button | KeymapperMouseButtonMask); - break; - } - } + HandleMouseButtonDown(event.button.button, modState); return; case SDL_MOUSEBUTTONUP: MousePosition = { event.button.x, event.button.y }; - - if (sgbMouseDown == CLICK_LEFT && event.button.button == SDL_BUTTON_LEFT) { - LastMouseButtonAction = MouseActionType::None; - sgbMouseDown = CLICK_NONE; - LeftMouseUp(modState); - } else if (sgbMouseDown == CLICK_RIGHT && event.button.button == SDL_BUTTON_RIGHT) { - LastMouseButtonAction = MouseActionType::None; - sgbMouseDown = CLICK_NONE; - } else { - sgOptions.Keymapper.KeyReleased(event.button.button | KeymapperMouseButtonMask); - } - return; - case SDL_JOYBUTTONDOWN: - PressControllerButton(static_cast(event.jbutton.button)); - return; - case SDL_JOYBUTTONUP: - sgOptions.Padmapper.ButtonReleased(static_cast(event.jbutton.button)); + HandleMouseButtonUp(event.button.button, modState); return; default: if (IsCustomEvent(event.type)) { diff --git a/Source/miniwin/misc_msg.cpp b/Source/miniwin/misc_msg.cpp index e0b9fe447..f505d63ba 100644 --- a/Source/miniwin/misc_msg.cpp +++ b/Source/miniwin/misc_msg.cpp @@ -8,11 +8,8 @@ #include "control.h" #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" #ifndef USE_SDL1 #include "controls/touch/event_handlers.h" #endif @@ -20,15 +17,11 @@ #include "engine/demomode.h" #include "engine/rectangle.hpp" #include "hwcursor.hpp" -#include "inv.h" -#include "menu.h" #include "movie.h" #include "panels/spell_list.hpp" #include "qol/stash.h" #include "utils/display.h" #include "utils/log.hpp" -#include "utils/sdl_compat.h" -#include "utils/stubs.h" #include "utils/utf8.hpp" #ifdef __vita__ @@ -154,52 +147,20 @@ bool FetchMessage_Real(SDL_Event *event, uint16_t *modState) } #endif - const ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(e); - bool isGamepadMotion = ProcessControllerMotion(e, ctrlEvent); - - DetectInputMethod(e, ctrlEvent); - if (isGamepadMotion) { - return true; - } - - if (movie_playing && SkipsMovie(ctrlEvent)) { - event->type = SDL_KEYDOWN; - return true; - } - - if (ctrlEvent.button != ControllerButton_NONE) { - if (ctrlEvent.button == SuppressedButton) { - if (!ctrlEvent.up) - return true; - SuppressedButton = ControllerButton_NONE; - } - - event->type = ctrlEvent.up ? SDL_JOYBUTTONUP : SDL_JOYBUTTONDOWN; - event->jbutton.button = ctrlEvent.button; - event->jbutton.state = ctrlEvent.up ? SDL_RELEASED : SDL_PRESSED; - } - - GameAction action; - if (GetGameAction(e, ctrlEvent, &action)) { - if (action.type == GameActionType_SEND_KEY) { - if ((action.send_key.vk_code & KeymapperMouseButtonMask) != 0) { - const unsigned button = action.send_key.vk_code & ~KeymapperMouseButtonMask; - SetMouseButtonEvent(*event, action.send_key.up ? SDL_MOUSEBUTTONUP : SDL_MOUSEBUTTONDOWN, static_cast(button), MousePosition); - } else { - event->type = action.send_key.up ? SDL_KEYUP : SDL_KEYDOWN; - event->key.state = action.send_key.up ? SDL_PRESSED : SDL_RELEASED; - event->key.keysym.sym = static_cast(action.send_key.vk_code); - } - } else { - ProcessGameAction(action); - } - return true; - } - if (HandleControllerAddedOrRemovedEvent(e)) return true; switch (e.type) { +#ifndef USE_SDL1 + case SDL_CONTROLLERAXISMOTION: + case SDL_CONTROLLERBUTTONDOWN: + case SDL_CONTROLLERBUTTONUP: +#endif + case SDL_JOYAXISMOTION: + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + *event = e; + break; case SDL_KEYDOWN: case SDL_KEYUP: { #ifdef USE_SDL1 @@ -215,14 +176,9 @@ bool FetchMessage_Real(SDL_Event *event, uint16_t *modState) } } #endif - SDL_Keycode key = e.key.keysym.sym; - remap_keyboard_key(&key); - if (key == -1) + if (e.key.keysym.sym == -1) return FalseAvail(e.type == SDL_KEYDOWN ? "SDL_KEYDOWN" : "SDL_KEYUP", e.key.keysym.sym); - event->type = e.type; - event->key.state = e.key.state; - event->key.keysym.sym = key; - event->key.keysym.mod = e.key.keysym.mod; + *event = e; } break; case SDL_MOUSEMOTION: *event = e; diff --git a/Source/movie.cpp b/Source/movie.cpp index 4cc76e44c..6a4dbe2a1 100644 --- a/Source/movie.cpp +++ b/Source/movie.cpp @@ -41,6 +41,9 @@ void play_movie(const char *pszMovie, bool userCanClose) uint16_t modState; while (movie_playing) { while (movie_playing && FetchMessage(&event, &modState)) { + ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event); + if (userCanClose && SkipsMovie(ctrlEvent)) + movie_playing = false; switch (event.type) { case SDL_KEYDOWN: case SDL_MOUSEBUTTONUP: