From 6b2481a76cd5fa8027e28c06736e6f0ee38fe302 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Fri, 24 Dec 2021 03:39:55 +0100 Subject: [PATCH] Touch support on all SDL2 platforms --- CMake/Assets.cmake | 2 +- CMake/Definitions.cmake | 1 - CMake/platforms/android.cmake | 1 - CMake/platforms/ios.cmake | 1 - CMake/platforms/switch.cmake | 1 + CMakeLists.txt | 4 - Source/CMakeLists.txt | 4 +- Source/DiabloUI/diabloui.cpp | 19 +- Source/DiabloUI/selhero.cpp | 3 +- Source/control.cpp | 66 +++--- Source/control.h | 1 + Source/controls/controller.cpp | 2 + Source/controls/controller_motion.cpp | 15 +- Source/controls/devices/game_controller.cpp | 7 - Source/controls/devices/game_controller.h | 3 - Source/controls/devices/joystick.cpp | 5 - Source/controls/game_controls.cpp | 120 ++++++----- Source/controls/menu_controls.cpp | 9 - Source/controls/plrctrls.cpp | 177 ++++++++++++---- Source/controls/plrctrls.h | 14 +- Source/controls/touch/event_handlers.cpp | 11 - Source/controls/touch/event_handlers.h | 4 - Source/controls/touch/gamepad.h | 4 - Source/controls/touch/renderers.cpp | 1 + Source/controls/touch/renderers.h | 4 - Source/diablo.cpp | 16 +- Source/dx.cpp | 13 +- Source/inv.cpp | 2 +- Source/miniwin/miniwin.h | 3 +- Source/miniwin/misc_msg.cpp | 68 +++--- Source/missiles.cpp | 13 +- Source/platform/vita/touch.cpp | 221 +++++++++----------- Source/platform/vita/touch.h | 6 +- Source/player.cpp | 5 +- Source/scrollrt.cpp | 9 +- Source/scrollrt.h | 5 - Source/trigs.cpp | 3 +- Source/utils/display.cpp | 10 +- 38 files changed, 445 insertions(+), 408 deletions(-) diff --git a/CMake/Assets.cmake b/CMake/Assets.cmake index c4569dcee..d674ff5d5 100644 --- a/CMake/Assets.cmake +++ b/CMake/Assets.cmake @@ -145,7 +145,7 @@ set(devilutionx_assets ui_art/mainmenuw.pcx ui_art/supportw.pcx) -if(VIRTUAL_GAMEPAD) +if(NOT USE_SDL1 AND NOT VITA) list(APPEND devilutionx_assets ui_art/button.png ui_art/directions2.png diff --git a/CMake/Definitions.cmake b/CMake/Definitions.cmake index 4cc7f15c9..fdafb4aff 100644 --- a/CMake/Definitions.cmake +++ b/CMake/Definitions.cmake @@ -14,7 +14,6 @@ foreach( GPERF_HEAP_FIRST_GAME_ITERATION STREAM_ALL_AUDIO PACKET_ENCRYPTION - VIRTUAL_GAMEPAD ) if(${def_name}) list(APPEND DEVILUTIONX_DEFINITIONS ${def_name}) diff --git a/CMake/platforms/android.cmake b/CMake/platforms/android.cmake index d99d4a353..d4a452905 100644 --- a/CMake/platforms/android.cmake +++ b/CMake/platforms/android.cmake @@ -1,6 +1,5 @@ # General build options. set(BUILD_TESTING OFF) -set(VIRTUAL_GAMEPAD ON) # Disable all system dependencies. # All of these will be fetched via FetchContent and linked statically. diff --git a/CMake/platforms/ios.cmake b/CMake/platforms/ios.cmake index c9875b2af..7443929c4 100644 --- a/CMake/platforms/ios.cmake +++ b/CMake/platforms/ios.cmake @@ -1,6 +1,5 @@ # General build options. set(BUILD_TESTING OFF) -set(VIRTUAL_GAMEPAD ON) # Disable all system dependencies. # All of these will be fetched via FetchContent and linked statically. diff --git a/CMake/platforms/switch.cmake b/CMake/platforms/switch.cmake index 733baf82e..b34d109b0 100644 --- a/CMake/platforms/switch.cmake +++ b/CMake/platforms/switch.cmake @@ -4,6 +4,7 @@ set(ASAN OFF) set(UBSAN OFF) set(BUILD_TESTING OFF) +set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF) set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) set(DISABLE_ZERO_TIER ON) set(PREFILL_PLAYER_NAME ON) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5401b811..a08b694b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,10 +63,6 @@ if(TSAN) set(ASAN OFF) endif() -if(USE_SDL1) - set(VIRTUAL_GAMEPAD OFF) -endif() - # By default, devilutionx.mpq is built only if smpq is installed. if(NOT DEFINED BUILD_ASSETS_MPQ AND NOT SRC_DIST) find_program(SMPQ smpq) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 32fd10319..161e6e222 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -74,7 +74,6 @@ set(libdevilutionx_SRCS controls/axis_direction.cpp controls/controller.cpp controls/controller_motion.cpp - controls/devices/game_controller.cpp controls/devices/joystick.cpp controls/devices/kbcontroller.cpp controls/game_controls.cpp @@ -178,8 +177,9 @@ if(NOT NONET) endif() endif() -if(VIRTUAL_GAMEPAD) +if(NOT USE_SDL1) list(APPEND libdevilutionx_SRCS + controls/devices/game_controller.cpp controls/touch/event_handlers.cpp controls/touch/gamepad.cpp controls/touch/renderers.cpp) diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index db3dca622..9ab7df1c8 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/Source/DiabloUI/diabloui.cpp @@ -15,6 +15,7 @@ #include "controls/controller.h" #include "controls/input.h" #include "controls/menu_controls.h" +#include "controls/plrctrls.h" #include "discord/discord.h" #include "dx.h" #include "hwcursor.hpp" @@ -340,20 +341,6 @@ void UiFocusNavigation(SDL_Event *event) break; } -#ifndef USE_SDL1 - // SDL generates mouse events from touch-based inputs to provide basic - // touchscreeen support for apps that don't explicitly handle touch events - sgbTouchActive = false; - if (IsAnyOf(event->type, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP) && event->button.which == SDL_TOUCH_MOUSEID) - sgbTouchActive = true; - if (event->type == SDL_MOUSEMOTION && event->motion.which == SDL_TOUCH_MOUSEID) - sgbTouchActive = true; - if (event->type == SDL_MOUSEWHEEL && event->wheel.which == SDL_TOUCH_MOUSEID) - sgbTouchActive = true; - if (IsAnyOf(event->type, SDL_FINGERDOWN, SDL_FINGERUP, SDL_FINGERMOTION)) - sgbTouchActive = true; -#endif - if (HandleMenuAction(GetMenuAction(*event))) return; @@ -762,7 +749,7 @@ void UiPollAndRender(std::function eventHandler) // Must happen after the very first UiFadeIn, which sets the cursor. if (IsHardwareCursor()) - SetHardwareCursorVisible(!sgbControllerActive); + SetHardwareCursorVisible(ControlMode == ControlTypes::KeyboardAndMouse); #ifdef __3DS__ // Keyboard blocks until input is finished @@ -1087,7 +1074,7 @@ bool UiItemMouseEvents(SDL_Event *event, const std::vector PANEL_WIDTH) { - LeftPanel.position.x = (gnScreenWidth - LeftPanel.size.width - RightPanel.size.width - PANEL_WIDTH) / 2; - } -#endif - LeftPanel.position.y = (gnScreenHeight - LeftPanel.size.height - PANEL_HEIGHT) / 2; - -#ifdef VIRTUAL_GAMEPAD - RightPanel.position.x = gnScreenWidth / 2; -#else - RightPanel.position.x = gnScreenWidth - RightPanel.size.width - LeftPanel.position.x; -#endif - RightPanel.position.y = LeftPanel.position.y; -} - /** * Draws a section of the empty flask cel on top of the panel to create the illusion * of the flask getting empty. This function takes a cel and draws a @@ -413,6 +383,38 @@ void RemoveGold(Player &player, int goldIndex) } // namespace +void CalculatePanelAreas() +{ + MainPanel = { + { (gnScreenWidth - PANEL_WIDTH) / 2, gnScreenHeight - PANEL_HEIGHT }, + { PANEL_WIDTH, PANEL_HEIGHT } + }; + LeftPanel = { + { 0, 0 }, + { SPANEL_WIDTH, SPANEL_HEIGHT } + }; + RightPanel = { + { 0, 0 }, + { SPANEL_WIDTH, SPANEL_HEIGHT } + }; + + if (ControlMode == ControlTypes::VirtualGamepad) { + LeftPanel.position.x = gnScreenWidth / 2 - LeftPanel.size.width; + } else { + if (gnScreenWidth - LeftPanel.size.width - RightPanel.size.width > PANEL_WIDTH) { + LeftPanel.position.x = (gnScreenWidth - LeftPanel.size.width - RightPanel.size.width - PANEL_WIDTH) / 2; + } + } + LeftPanel.position.y = (gnScreenHeight - LeftPanel.size.height - PANEL_HEIGHT) / 2; + + if (ControlMode == ControlTypes::VirtualGamepad) { + RightPanel.position.x = gnScreenWidth / 2; + } else { + RightPanel.position.x = gnScreenWidth - RightPanel.size.width - LeftPanel.position.x; + } + RightPanel.position.y = LeftPanel.position.y; +} + bool IsChatAvailable() { #ifdef _DEBUG diff --git a/Source/control.h b/Source/control.h index ecdf78ef8..eac77975d 100644 --- a/Source/control.h +++ b/Source/control.h @@ -59,6 +59,7 @@ const Rectangle &GetRightPanel(); extern std::optional pBtmBuff; extern SDL_Rect PanBtnPos[8]; +void CalculatePanelAreas(); bool IsChatAvailable(); /** * @brief Check if the UI can cover the game area entierly diff --git a/Source/controls/controller.cpp b/Source/controls/controller.cpp index 52db9c1d0..960eea77f 100644 --- a/Source/controls/controller.cpp +++ b/Source/controls/controller.cpp @@ -2,7 +2,9 @@ #include +#ifndef USE_SDL1 #include "controls/devices/game_controller.h" +#endif #include "controls/devices/joystick.h" #include "controls/devices/kbcontroller.h" diff --git a/Source/controls/controller_motion.cpp b/Source/controls/controller_motion.cpp index f065370f7..5eb9d0f55 100644 --- a/Source/controls/controller_motion.cpp +++ b/Source/controls/controller_motion.cpp @@ -3,10 +3,13 @@ #include #include "controls/controller.h" +#ifndef USE_SDL1 #include "controls/devices/game_controller.h" +#endif #include "controls/devices/joystick.h" #include "controls/devices/kbcontroller.h" #include "controls/game_controls.h" +#include "controls/plrctrls.h" #include "controls/touch/gamepad.h" #include "options.h" @@ -160,11 +163,13 @@ AxisDirection GetLeftStickOrDpadDirection(bool allowDpad) bool isLeftPressed = stickX <= -0.5 || (allowDpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_LEFT)); bool isRightPressed = stickX >= 0.5 || (allowDpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_RIGHT)); -#ifdef VIRTUAL_GAMEPAD - isUpPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isUpPressed; - isDownPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isDownPressed; - isLeftPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isLeftPressed; - isRightPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isRightPressed; +#ifndef USE_SDL1 + if (ControlMode == ControlTypes::VirtualGamepad) { + isUpPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isUpPressed; + isDownPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isDownPressed; + isLeftPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isLeftPressed; + isRightPressed |= VirtualGamepadState.isActive && VirtualGamepadState.directionPad.isRightPressed; + } #endif if (isUpPressed) { diff --git a/Source/controls/devices/game_controller.cpp b/Source/controls/devices/game_controller.cpp index dc76674cd..23d3bcedb 100644 --- a/Source/controls/devices/game_controller.cpp +++ b/Source/controls/devices/game_controller.cpp @@ -1,7 +1,5 @@ #include "controls/devices/game_controller.h" -#ifndef USE_SDL1 - #include #include "controls/controller_motion.h" @@ -13,9 +11,6 @@ namespace devilution { -// Defined in SourceX/controls/plctrls.cpp -extern bool sgbControllerActive; - std::vector GameController::controllers_; void GameController::UnlockTriggerState() @@ -189,7 +184,6 @@ void GameController::Remove(SDL_JoystickID instanceId) if (controller.instance_id_ != instanceId) continue; controllers_.erase(controllers_.begin() + i); - sgbControllerActive = !controllers_.empty(); return; } Log("Game controller not found with instance id: {}", instanceId); @@ -231,4 +225,3 @@ bool GameController::IsPressedOnAnyController(ControllerButton button) } } // namespace devilution -#endif diff --git a/Source/controls/devices/game_controller.h b/Source/controls/devices/game_controller.h index cdefe920d..314dea024 100644 --- a/Source/controls/devices/game_controller.h +++ b/Source/controls/devices/game_controller.h @@ -1,4 +1,3 @@ - #pragma once #include @@ -7,7 +6,6 @@ #include "controls/controller_buttons.h" -#ifndef USE_SDL1 namespace devilution { class GameController { @@ -42,4 +40,3 @@ private: }; } // namespace devilution -#endif diff --git a/Source/controls/devices/joystick.cpp b/Source/controls/devices/joystick.cpp index a834d727a..8d2475896 100644 --- a/Source/controls/devices/joystick.cpp +++ b/Source/controls/devices/joystick.cpp @@ -8,9 +8,6 @@ namespace devilution { -// Defined in SourceX/controls/plctrls.cpp -extern bool sgbControllerActive; - std::vector Joystick::joysticks_; ControllerButton Joystick::ToControllerButton(const SDL_Event &event) @@ -267,7 +264,6 @@ void Joystick::Add(int deviceIndex) result.instance_id_ = SDL_JoystickInstanceID(result.sdl_joystick_); #endif joysticks_.push_back(result); - sgbControllerActive = true; } void Joystick::Remove(SDL_JoystickID instanceId) @@ -279,7 +275,6 @@ void Joystick::Remove(SDL_JoystickID instanceId) if (joystick.instance_id_ != instanceId) continue; joysticks_.erase(joysticks_.begin() + i); - sgbControllerActive = !joysticks_.empty(); return; } Log("Joystick not found with instance id: {}", instanceId); diff --git a/Source/controls/game_controls.cpp b/Source/controls/game_controls.cpp index 313be2ca6..2b8ce553c 100644 --- a/Source/controls/game_controls.cpp +++ b/Source/controls/game_controls.cpp @@ -4,7 +4,9 @@ #include "controls/controller.h" #include "controls/controller_motion.h" +#ifndef USE_SDL1 #include "controls/devices/game_controller.h" +#endif #include "controls/devices/joystick.h" #include "controls/menu_controls.h" #include "controls/modifier_hints.h" @@ -98,65 +100,67 @@ bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrlEvent, Game { const bool inGameMenu = InGameMenu(); -#ifdef VIRTUAL_GAMEPAD - if (event.type == SDL_FINGERDOWN) { - if (VirtualGamepadState.menuPanel.charButton.isHeld && VirtualGamepadState.menuPanel.charButton.didStateChange) { - *action = GameAction(GameActionType_TOGGLE_CHARACTER_INFO); - return true; - } - if (VirtualGamepadState.menuPanel.questsButton.isHeld && VirtualGamepadState.menuPanel.questsButton.didStateChange) { - *action = GameAction(GameActionType_TOGGLE_QUEST_LOG); - return true; - } - if (VirtualGamepadState.menuPanel.inventoryButton.isHeld && VirtualGamepadState.menuPanel.inventoryButton.didStateChange) { - *action = GameAction(GameActionType_TOGGLE_INVENTORY); - return true; - } - if (VirtualGamepadState.menuPanel.mapButton.isHeld && VirtualGamepadState.menuPanel.mapButton.didStateChange) { - *action = GameActionSendKey { DVL_VK_TAB, false }; - return true; - } - if (VirtualGamepadState.primaryActionButton.isHeld && VirtualGamepadState.primaryActionButton.didStateChange) { - if (!inGameMenu && !QuestLogIsOpen && !sbookflag) - *action = GameAction(GameActionType_PRIMARY_ACTION); - else if (sgpCurrentMenu != nullptr || stextflag != STORE_NONE || QuestLogIsOpen) - *action = GameActionSendKey { DVL_VK_RETURN, false }; - else - *action = GameActionSendKey { DVL_VK_SPACE, false }; - return true; - } - if (VirtualGamepadState.secondaryActionButton.isHeld && VirtualGamepadState.secondaryActionButton.didStateChange) { - if (!inGameMenu && !QuestLogIsOpen && !sbookflag) - *action = GameAction(GameActionType_SECONDARY_ACTION); - return true; - } - if (VirtualGamepadState.spellActionButton.isHeld && VirtualGamepadState.spellActionButton.didStateChange) { - if (!inGameMenu && !QuestLogIsOpen && !sbookflag) - *action = GameAction(GameActionType_CAST_SPELL); - return true; - } - if (VirtualGamepadState.cancelButton.isHeld && VirtualGamepadState.cancelButton.didStateChange) { - if (inGameMenu || DoomFlag || spselflag) - *action = GameActionSendKey { DVL_VK_ESCAPE, false }; - else if (invflag) - *action = GameAction(GameActionType_TOGGLE_INVENTORY); - else if (sbookflag) - *action = GameAction(GameActionType_TOGGLE_SPELL_BOOK); - else if (QuestLogIsOpen) - *action = GameAction(GameActionType_TOGGLE_QUEST_LOG); - else if (chrflag) +#ifndef USE_SDL1 + if (ControlMode == ControlTypes::VirtualGamepad) { + if (event.type == SDL_FINGERDOWN) { + if (VirtualGamepadState.menuPanel.charButton.isHeld && VirtualGamepadState.menuPanel.charButton.didStateChange) { *action = GameAction(GameActionType_TOGGLE_CHARACTER_INFO); - return true; - } - if (VirtualGamepadState.healthButton.isHeld && VirtualGamepadState.healthButton.didStateChange) { - if (!QuestLogIsOpen && !sbookflag && stextflag == STORE_NONE) - *action = GameAction(GameActionType_USE_HEALTH_POTION); - return true; - } - if (VirtualGamepadState.manaButton.isHeld && VirtualGamepadState.manaButton.didStateChange) { - if (!QuestLogIsOpen && !sbookflag && stextflag == STORE_NONE) - *action = GameAction(GameActionType_USE_MANA_POTION); - return true; + return true; + } + if (VirtualGamepadState.menuPanel.questsButton.isHeld && VirtualGamepadState.menuPanel.questsButton.didStateChange) { + *action = GameAction(GameActionType_TOGGLE_QUEST_LOG); + return true; + } + if (VirtualGamepadState.menuPanel.inventoryButton.isHeld && VirtualGamepadState.menuPanel.inventoryButton.didStateChange) { + *action = GameAction(GameActionType_TOGGLE_INVENTORY); + return true; + } + if (VirtualGamepadState.menuPanel.mapButton.isHeld && VirtualGamepadState.menuPanel.mapButton.didStateChange) { + *action = GameActionSendKey { DVL_VK_TAB, false }; + return true; + } + if (VirtualGamepadState.primaryActionButton.isHeld && VirtualGamepadState.primaryActionButton.didStateChange) { + if (!inGameMenu && !QuestLogIsOpen && !sbookflag) + *action = GameAction(GameActionType_PRIMARY_ACTION); + else if (sgpCurrentMenu != nullptr || stextflag != STORE_NONE || QuestLogIsOpen) + *action = GameActionSendKey { DVL_VK_RETURN, false }; + else + *action = GameActionSendKey { DVL_VK_SPACE, false }; + return true; + } + if (VirtualGamepadState.secondaryActionButton.isHeld && VirtualGamepadState.secondaryActionButton.didStateChange) { + if (!inGameMenu && !QuestLogIsOpen && !sbookflag) + *action = GameAction(GameActionType_SECONDARY_ACTION); + return true; + } + if (VirtualGamepadState.spellActionButton.isHeld && VirtualGamepadState.spellActionButton.didStateChange) { + if (!inGameMenu && !QuestLogIsOpen && !sbookflag) + *action = GameAction(GameActionType_CAST_SPELL); + return true; + } + if (VirtualGamepadState.cancelButton.isHeld && VirtualGamepadState.cancelButton.didStateChange) { + if (inGameMenu || DoomFlag || spselflag) + *action = GameActionSendKey { DVL_VK_ESCAPE, false }; + else if (invflag) + *action = GameAction(GameActionType_TOGGLE_INVENTORY); + else if (sbookflag) + *action = GameAction(GameActionType_TOGGLE_SPELL_BOOK); + else if (QuestLogIsOpen) + *action = GameAction(GameActionType_TOGGLE_QUEST_LOG); + else if (chrflag) + *action = GameAction(GameActionType_TOGGLE_CHARACTER_INFO); + return true; + } + if (VirtualGamepadState.healthButton.isHeld && VirtualGamepadState.healthButton.didStateChange) { + if (!QuestLogIsOpen && !sbookflag && stextflag == STORE_NONE) + *action = GameAction(GameActionType_USE_HEALTH_POTION); + return true; + } + if (VirtualGamepadState.manaButton.isHeld && VirtualGamepadState.manaButton.didStateChange) { + if (!QuestLogIsOpen && !sbookflag && stextflag == STORE_NONE) + *action = GameAction(GameActionType_USE_MANA_POTION); + return true; + } } } #endif diff --git a/Source/controls/menu_controls.cpp b/Source/controls/menu_controls.cpp index 914e98053..43e9770be 100644 --- a/Source/controls/menu_controls.cpp +++ b/Source/controls/menu_controls.cpp @@ -28,13 +28,9 @@ MenuAction GetMenuAction(const SDL_Event &event) const ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event); if (ProcessControllerMotion(event, ctrlEvent)) { - sgbControllerActive = true; return GetMenuHeldUpDownAction(); } - if (ctrlEvent.button != ControllerButton_NONE) - sgbControllerActive = true; - if (!ctrlEvent.up) { switch (ctrlEvent.button) { case ControllerButton_IGNORE: @@ -64,8 +60,6 @@ MenuAction GetMenuAction(const SDL_Event &event) } if (event.type == SDL_MOUSEBUTTONDOWN) { - sgbControllerActive = false; - switch (event.button.button) { case SDL_BUTTON_X1: #if !SDL_VERSION_ATLEAST(2, 0, 0) @@ -76,9 +70,6 @@ MenuAction GetMenuAction(const SDL_Event &event) } #if HAS_KBCTRL == 0 - if (event.type >= SDL_KEYDOWN && event.type < SDL_JOYAXISMOTION) - sgbControllerActive = false; - if (event.type == SDL_KEYDOWN) { auto sym = event.key.keysym.sym; remap_keyboard_key(&sym); diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 356663258..6b5d86533 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -8,6 +8,9 @@ #include "control.h" #include "controls/controller.h" #include "controls/controller_motion.h" +#ifndef USE_SDL1 +#include "controls/devices/game_controller.h" +#endif #include "controls/game_controls.h" #include "controls/touch/gamepad.h" #include "cursor.h" @@ -29,8 +32,7 @@ namespace devilution { -bool sgbTouchActive = false; -bool sgbControllerActive = false; +ControlTypes ControlMode = ControlTypes::None; int pcurstrig = -1; int pcursmissile = -1; quest_id pcursquest = Q_INVALID; @@ -456,8 +458,10 @@ void Interact() } bool stand = false; -#ifdef VIRTUAL_GAMEPAD - stand = VirtualGamepadState.standButton.isHeld; +#ifndef USE_SDL1 + if (ControlMode == ControlTypes::VirtualGamepad) { + stand = VirtualGamepadState.standButton.isHeld; + } #endif if (leveltype != DTYPE_TOWN && stand) { @@ -1117,7 +1121,7 @@ void WalkInDir(int playerId, AxisDirection dir) auto &player = Players[playerId]; if (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE) { - if (sgbControllerActive && player.walkpath[0] != WALK_NONE && player.destAction == ACTION_NONE) + if (ControlMode != ControlTypes::KeyboardAndMouse && player.walkpath[0] != WALK_NONE && player.destAction == ACTION_NONE) NetSendCmdLoc(playerId, true, CMD_WALKXY, player.position.future); // Stop walking return; } @@ -1128,11 +1132,13 @@ void WalkInDir(int playerId, AxisDirection dir) if (!player.IsWalking() && player.CanChangeAction()) player._pdir = pdir; -#ifdef VIRTUAL_GAMEPAD - if (VirtualGamepadState.standButton.isHeld) { - if (player._pmode == PM_STAND) - StartStand(playerId, pdir); - return; +#ifndef USE_SDL1 + if (ControlMode == ControlTypes::VirtualGamepad) { + if (VirtualGamepadState.standButton.isHeld) { + if (player._pmode == PM_STAND) + StartStand(playerId, pdir); + return; + } } #endif @@ -1204,13 +1210,8 @@ void Movement(int playerId) || IsControllerButtonPressed(ControllerButton_BUTTON_BACK)) return; - AxisDirection moveDir = GetMoveDirection(); - if (moveDir.x != AxisDirectionX_NONE || moveDir.y != AxisDirectionY_NONE) { - sgbControllerActive = true; - } - if (GetLeftStickOrDPadGameUIHandler() == nullptr) { - WalkInDir(playerId, moveDir); + WalkInDir(playerId, GetMoveDirection()); } } @@ -1249,16 +1250,103 @@ struct RightStickAccumulator { float hiresDY; }; +ControlTypes GetInputTypeFromEvent(SDL_Event &event) +{ + if (IsAnyOf(event.type, SDL_KEYDOWN, SDL_KEYUP)) + return ControlTypes::KeyboardAndMouse; +#ifdef USE_SDL1 + if (IsAnyOf(event.type, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP, SDL_MOUSEMOTION)) + return ControlTypes::KeyboardAndMouse; +#else + if (IsAnyOf(event.type, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP)) + return event.button.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse; + if (event.type == SDL_MOUSEMOTION) + return event.motion.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse; + if (event.type == SDL_MOUSEWHEEL) + return event.wheel.which == SDL_TOUCH_MOUSEID ? ControlTypes::VirtualGamepad : ControlTypes::KeyboardAndMouse; + if (IsAnyOf(event.type, SDL_FINGERDOWN, SDL_FINGERUP, SDL_FINGERMOTION)) + return ControlTypes::VirtualGamepad; + if (event.type >= SDL_CONTROLLERAXISMOTION && event.type <= SDL_CONTROLLERDEVICEREMAPPED) + return ControlTypes::Gamepad; + if (IsAnyOf(event.type, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED)) + return ControlTypes::Gamepad; +#endif + if (event.type >= SDL_JOYAXISMOTION && event.type <= SDL_JOYBUTTONUP) + return ControlTypes::Gamepad; + + return ControlTypes::None; +} + +bool ContinueSimulatingMouse(SDL_Event &event) +{ + if (IsAutomapActive()) + return false; + + if (event.type == SDL_JOYAXISMOTION) { +#if defined(JOY_AXIS_RIGHTX) + if (event.jaxis.axis == JOY_AXIS_RIGHTX) + return true; +#endif +#if defined(JOY_AXIS_RIGHTY) + if (event.jaxis.axis == JOY_AXIS_RIGHTY) + return true; +#endif +#ifndef USE_SDL1 +#if !defined(JOY_AXIS_RIGHTX) && !defined(JOY_AXIS_RIGHTY) + if (!GameController::All().empty()) + return true; +#endif + } else if (event.type == SDL_CONTROLLERAXISMOTION && IsAnyOf(event.caxis.axis, SDL_CONTROLLER_AXIS_RIGHTX, SDL_CONTROLLER_AXIS_RIGHTY)) { + return true; +#endif +#ifdef USE_SDL1 + } else if (IsAnyOf(event.type, SDL_JOYBUTTONUP, SDL_JOYBUTTONDOWN, SDL_KEYUP, SDL_KEYDOWN)) { +#else + } else if (IsAnyOf(event.type, SDL_JOYBUTTONUP, SDL_JOYBUTTONDOWN, SDL_KEYUP, SDL_KEYDOWN, SDL_CONTROLLERBUTTONUP, SDL_CONTROLLERBUTTONDOWN)) { +#endif + const ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event); + if (IsAnyOf(ctrlEvent.button, ControllerButton_BUTTON_RIGHTSTICK, ControllerButton_BUTTON_BACK, ControllerButton_NONE, ControllerButton_IGNORE)) { + return true; + } + } + + return false; +} + } // namespace -bool IsAutomapActive() +void DetectInputMethod(SDL_Event &event) { - return AutomapActive && leveltype != DTYPE_TOWN; + ControlTypes inputType = GetInputTypeFromEvent(event); + +#ifdef __vita__ + if (inputType == ControlTypes::VirtualGamepad) { + inputType = ControlTypes::Gamepad; + } +#endif + +#if HAS_KBCTRL == 1 + if (inputType == ControlTypes::KeyboardAndMouse) { + const ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event); + if (!IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE)) { + inputType = ControlTypes::Gamepad; + } + } +#endif + + if (ControlMode == ControlTypes::KeyboardAndMouse && inputType == ControlTypes::Gamepad && ContinueSimulatingMouse(event)) { + return; + } + + if (inputType != ControlTypes::None && inputType != ControlMode) { + ControlMode = inputType; + CalculatePanelAreas(); + } } -bool IsMovingMouseCursorWithController() +bool IsAutomapActive() { - return rightStickX != 0 || rightStickY != 0; + return AutomapActive && leveltype != DTYPE_TOWN; } void HandleRightStickMotion() @@ -1280,7 +1368,6 @@ void HandleRightStickMotion() } { // move cursor - sgbControllerActive = false; InvalidateInventorySlot(); int x = MousePosition.x; int y = MousePosition.y; @@ -1317,29 +1404,31 @@ void FocusOnInventory() void plrctrls_after_check_curs_move() { // check for monsters first, then items, then towners. - if (sgbControllerActive) { - // Clear focuse set by cursor - pcursplr = -1; - pcursmonst = -1; - pcursitem = -1; - pcursobj = -1; - pcursmissile = -1; - pcurstrig = -1; - pcursquest = Q_INVALID; - cursPosition = { -1, -1 }; - if (Players[MyPlayerId]._pInvincible) { - return; - } - if (DoomFlag) { - return; - } - if (!invflag) { - *infostr = '\0'; - ClearPanel(); - FindActor(); - FindItemOrObject(); - FindTrigger(); - } + if (ControlMode == ControlTypes::KeyboardAndMouse) { + return; + } + + // Clear focuse set by cursor + pcursplr = -1; + pcursmonst = -1; + pcursitem = -1; + pcursobj = -1; + pcursmissile = -1; + pcurstrig = -1; + pcursquest = Q_INVALID; + cursPosition = { -1, -1 }; + if (Players[MyPlayerId]._pInvincible) { + return; + } + if (DoomFlag) { + return; + } + if (!invflag) { + *infostr = '\0'; + ClearPanel(); + FindActor(); + FindItemOrObject(); + FindTrigger(); } } diff --git a/Source/controls/plrctrls.h b/Source/controls/plrctrls.h index 137a20f07..27e9d2566 100644 --- a/Source/controls/plrctrls.h +++ b/Source/controls/plrctrls.h @@ -12,6 +12,15 @@ typedef enum belt_item_type : uint8_t { BLT_MANA, } belt_item_type; +enum class ControlTypes : uint8_t { + None, + KeyboardAndMouse, + Gamepad, + VirtualGamepad, +}; + +extern ControlTypes ControlMode; + // Runs every frame. // Handles menu movement. void plrctrls_every_frame(); @@ -30,12 +39,11 @@ void HandleRightStickMotion(); // Whether we're in a dialog menu that the game handles natively with keyboard controls. bool InGameMenu(); +void DetectInputMethod(SDL_Event &event); + // Whether the automap is being displayed. bool IsAutomapActive(); -// Whether the mouse cursor is being moved with the controller. -bool IsMovingMouseCursorWithController(); - void UseBeltItem(int type); // Talk to towners, click on inv items, attack, etc. diff --git a/Source/controls/touch/event_handlers.cpp b/Source/controls/touch/event_handlers.cpp index c3d733805..ce135adc2 100644 --- a/Source/controls/touch/event_handlers.cpp +++ b/Source/controls/touch/event_handlers.cpp @@ -1,5 +1,3 @@ -#ifndef USE_SDL1 - #include "controls/touch/event_handlers.h" #include "control.h" @@ -15,8 +13,6 @@ namespace devilution { -extern bool sgbTouchActive; - namespace { VirtualGamepadEventHandler Handler(&VirtualGamepadState); @@ -38,7 +34,6 @@ void SimulateMouseMovement(const SDL_Event &event) MousePosition = position; - sgbControllerActive = false; InvalidateInventorySlot(); } @@ -93,16 +88,12 @@ void HandleBottomPanelInteraction(const SDL_Event &event) void HandleTouchEvent(const SDL_Event &event) { - sgbTouchActive = false; - if (Handler.Handle(event)) return; if (!IsAnyOf(event.type, SDL_FINGERDOWN, SDL_FINGERUP, SDL_FINGERMOTION)) return; - sgbTouchActive = true; - SimulateMouseMovement(event); if (HandleGameMenuInteraction(event)) @@ -308,5 +299,3 @@ bool VirtualButtonEventHandler::HandleFingerMotion(const SDL_TouchFingerEvent &e } } // namespace devilution - -#endif diff --git a/Source/controls/touch/event_handlers.h b/Source/controls/touch/event_handlers.h index 7751c4cf1..afa0e3a25 100644 --- a/Source/controls/touch/event_handlers.h +++ b/Source/controls/touch/event_handlers.h @@ -1,7 +1,5 @@ #pragma once -#ifdef VIRTUAL_GAMEPAD - #include #include "controls/touch/gamepad.h" @@ -93,5 +91,3 @@ private: void HandleTouchEvent(const SDL_Event &event); } // namespace devilution - -#endif diff --git a/Source/controls/touch/gamepad.h b/Source/controls/touch/gamepad.h index c48979e68..14a8c7bb3 100644 --- a/Source/controls/touch/gamepad.h +++ b/Source/controls/touch/gamepad.h @@ -1,7 +1,5 @@ #pragma once -#ifdef VIRTUAL_GAMEPAD - #include #include "controls/controller_buttons.h" @@ -121,5 +119,3 @@ void DeactivateVirtualGamepad(); extern VirtualGamepad VirtualGamepadState; } // namespace devilution - -#endif diff --git a/Source/controls/touch/renderers.cpp b/Source/controls/touch/renderers.cpp index d4eccaf08..ac9c9dca3 100644 --- a/Source/controls/touch/renderers.cpp +++ b/Source/controls/touch/renderers.cpp @@ -1,4 +1,5 @@ #include "controls/touch/renderers.h" + #include "control.h" #include "cursor.h" #include "diablo.h" diff --git a/Source/controls/touch/renderers.h b/Source/controls/touch/renderers.h index 422b78e15..5946e660c 100644 --- a/Source/controls/touch/renderers.h +++ b/Source/controls/touch/renderers.h @@ -1,7 +1,5 @@ #pragma once -#ifdef VIRTUAL_GAMEPAD - #include #include "DiabloUI/art.h" @@ -224,5 +222,3 @@ void RenderVirtualGamepad(SDL_Surface *surface); void FreeVirtualGamepadGFX(); } // namespace devilution - -#endif diff --git a/Source/diablo.cpp b/Source/diablo.cpp index c6de57a18..53f632b18 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -198,7 +198,7 @@ bool ProcessInput() if (!gmenu_is_active() && sgnTimeoutCurs == CURSOR_NONE) { #ifdef __vita__ - finish_simulated_mouse_clicks(MousePosition.x, MousePosition.y); + FinishSimulatedMouseClicks(MousePosition); #endif CheckCursMove(); plrctrls_after_check_curs_move(); @@ -909,7 +909,7 @@ void DiabloParseFlags(int argc, char **argv) void DiabloInitScreen() { MousePosition = { gnScreenWidth / 2, gnScreenHeight / 2 }; - if (!sgbControllerActive) + if (ControlMode == ControlTypes::KeyboardAndMouse) SetCursorPos(MousePosition); ScrollInfo.tile = { 0, 0 }; ScrollInfo.offset = { 0, 0 }; @@ -953,7 +953,7 @@ void DiabloInit() messages.emplace_back(_(QuickMessages[i].message)); } -#ifdef VIRTUAL_GAMEPAD +#ifndef USE_SDL1 InitializeVirtualGamepad(); #endif @@ -1090,7 +1090,7 @@ void LoadLvlGFX() void LoadAllGFX() { IncProgress(); -#ifdef VIRTUAL_GAMEPAD +#if !defined(USE_SDL1) && !defined(__vita__) InitVirtualGamepadGFX(renderer); #endif IncProgress(); @@ -1563,7 +1563,7 @@ void FreeGameMem() FreeObjectGFX(); FreeMonsterSnd(); FreeTownerGFX(); -#ifdef VIRTUAL_GAMEPAD +#ifndef USE_SDL1 DeactivateVirtualGamepad(); FreeVirtualGamepadGFX(); #endif @@ -1908,7 +1908,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir) LoadAllGFX(); } else { IncProgress(); -#ifdef VIRTUAL_GAMEPAD +#if !defined(USE_SDL1) && !defined(__vita__) InitVirtualGamepadGFX(renderer); #endif IncProgress(); @@ -2014,7 +2014,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir) InitGolems(); InitMonsters(); IncProgress(); -#ifdef VIRTUAL_GAMEPAD +#if !defined(USE_SDL1) && !defined(__vita__) InitVirtualGamepadGFX(renderer); #endif InitMissileGFX(gbIsHellfire); @@ -2093,7 +2093,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir) } } -#ifdef VIRTUAL_GAMEPAD +#ifndef USE_SDL1 ActivateVirtualGamepad(); #endif diff --git a/Source/dx.cpp b/Source/dx.cpp index a3d893b5f..51854dca5 100644 --- a/Source/dx.cpp +++ b/Source/dx.cpp @@ -7,6 +7,7 @@ #include +#include "controls/plrctrls.h" #include "controls/touch/renderers.h" #include "engine.h" #include "options.h" @@ -283,18 +284,18 @@ void RenderPresent() if (SDL_RenderCopy(renderer, texture.get(), nullptr, nullptr) <= -1) { ErrSdl(); } -#ifdef VIRTUAL_GAMEPAD - RenderVirtualGamepad(renderer); -#endif + if (ControlMode == ControlTypes::VirtualGamepad) { + RenderVirtualGamepad(renderer); + } SDL_RenderPresent(renderer); if (!*sgOptions.Graphics.vSync) { LimitFrameRate(); } } else { -#ifdef VIRTUAL_GAMEPAD - RenderVirtualGamepad(surface); -#endif + if (ControlMode == ControlTypes::VirtualGamepad) { + RenderVirtualGamepad(surface); + } if (SDL_UpdateWindowSurface(ghMainWnd) <= -1) { ErrSdl(); } diff --git a/Source/inv.cpp b/Source/inv.cpp index 83a3b8d2c..8b13ffa0b 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -1345,7 +1345,7 @@ void DrawInvBelt(const Surface &out) const int celFrame = GetInvItemFrame(frame); if (pcursinvitem == i + INVITEM_BELT_FIRST) { - if (!sgbControllerActive || invflag) { + if (ControlMode == ControlTypes::KeyboardAndMouse || invflag) { CelBlitOutlineTo(out, GetOutlineColor(myPlayer.SpdList[i], true), position, cel, celFrame, false); } } diff --git a/Source/miniwin/miniwin.h b/Source/miniwin/miniwin.h index d2a144fb6..fc61d6722 100644 --- a/Source/miniwin/miniwin.h +++ b/Source/miniwin/miniwin.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -47,6 +47,7 @@ int TranslateSdlKey(SDL_Keysym key); bool GetAsyncKeyState(int vKey); +void SetMouseButtonEvent(SDL_Event &event, uint32_t type, uint8_t button, Point position); bool FetchMessage(tagMSG *lpMsg); bool TranslateMessage(const tagMSG *lpMsg); diff --git a/Source/miniwin/misc_msg.cpp b/Source/miniwin/misc_msg.cpp index 5ad08b06b..55845c52f 100644 --- a/Source/miniwin/misc_msg.cpp +++ b/Source/miniwin/misc_msg.cpp @@ -16,7 +16,9 @@ #include "controls/input.h" #include "controls/plrctrls.h" #include "controls/remap_keyboard.h" +#ifndef USE_SDL1 #include "controls/touch/event_handlers.h" +#endif #include "cursor.h" #include "engine/demomode.h" #include "engine/rectangle.hpp" @@ -53,6 +55,19 @@ static std::deque message_queue; bool mouseWarping = false; Point mousePositionWarping; +void SetMouseButtonEvent(SDL_Event &event, uint32_t type, uint8_t button, Point position) +{ + event.type = type; + event.button.button = button; + if (type == SDL_MOUSEBUTTONDOWN) { + event.button.state = SDL_PRESSED; + } else { + event.button.state = SDL_RELEASED; + } + event.button.x = position.x; + event.button.y = position.y; +} + void SetCursorPos(Point position) { mousePositionWarping = position; @@ -319,11 +334,24 @@ bool FetchMessage_Real(tagMSG *lpMsg) lpMsg->lParam = 0; lpMsg->wParam = 0; +#ifdef __vita__ + HandleTouchEvent(&e, MousePosition); +#elif !defined(USE_SDL1) + HandleTouchEvent(e); +#endif + if (e.type == SDL_QUIT) { lpMsg->message = DVL_WM_QUIT; return true; } + if ((e.type == SDL_KEYUP || e.type == SDL_KEYDOWN) && e.key.keysym.sym == SDLK_UNKNOWN) { + // Erroneous events generated by RG350 kernel. + return true; + } + + DetectInputMethod(e); + #if !defined(USE_SDL1) && !defined(__vita__) if (!movie_playing) { // SDL generates mouse events from touch-based inputs to provide basic @@ -337,27 +365,14 @@ bool FetchMessage_Real(tagMSG *lpMsg) } #endif -#ifdef VIRTUAL_GAMEPAD - HandleTouchEvent(e); -#endif - -#ifdef __vita__ - handle_touch(&e, MousePosition.x, MousePosition.y); -#endif - #ifdef USE_SDL1 if (e.type == SDL_MOUSEMOTION) { OutputToLogical(&e.motion.x, &e.motion.y); - } else if (e.type == SDL_MOUSEBUTTONDOWN || e.type == SDL_MOUSEBUTTONUP) { + } else if (IsAnyOf(e.type, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP)) { OutputToLogical(&e.button.x, &e.button.y); } #endif - if ((e.type == SDL_KEYUP || e.type == SDL_KEYDOWN) && e.key.keysym.sym == SDLK_UNKNOWN) { - // Erroneous events generated by RG350 kernel. - return true; - } - if (HandleControllerAddedOrRemovedEvent(e)) return true; @@ -368,8 +383,6 @@ bool FetchMessage_Real(tagMSG *lpMsg) GameAction action; if (GetGameAction(e, ctrlEvent, &action)) { if (action.type != GameActionType_NONE) { - sgbControllerActive = true; - if (movie_playing) { lpMsg->message = DVL_WM_KEYDOWN; if (action.type == GameActionType_SEND_KEY) @@ -450,27 +463,20 @@ bool FetchMessage_Real(tagMSG *lpMsg) lpMsg->wParam = action.send_key.vk_code; return true; case GameActionType_SEND_MOUSE_CLICK: - sgbControllerActive = false; - switch (action.send_mouse_click.button) { - case GameActionSendMouseClick::LEFT: - lpMsg->message = action.send_mouse_click.up ? DVL_WM_LBUTTONUP : DVL_WM_LBUTTONDOWN; - break; - case GameActionSendMouseClick::RIGHT: - lpMsg->message = action.send_mouse_click.up ? DVL_WM_RBUTTONUP : DVL_WM_RBUTTONDOWN; - break; - } - lpMsg->lParam = PositionForMouse(MousePosition.x, MousePosition.y); + Uint8 simulatedButton = action.send_mouse_click.button == GameActionSendMouseClick::LEFT ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT; + SDL_Event clickEvent; + SetMouseButtonEvent(clickEvent, action.send_mouse_click.up ? SDL_MOUSEBUTTONUP : SDL_MOUSEBUTTONDOWN, simulatedButton, MousePosition); + SDL_PushEvent(&clickEvent); break; } return true; -#ifdef __vita__ } + +#ifdef __vita__ if (e.type < SDL_JOYAXISMOTION || (e.type >= SDL_FINGERDOWN && e.type < SDL_DOLLARGESTURE)) { #else - } else if (e.type < SDL_JOYAXISMOTION) { + if (e.type < SDL_JOYAXISMOTION) { #endif - if (!mouseWarping || e.type != SDL_MOUSEMOTION) - sgbControllerActive = false; if (mouseWarping && e.type == SDL_MOUSEMOTION) mouseWarping = false; } @@ -506,7 +512,7 @@ bool FetchMessage_Real(tagMSG *lpMsg) lpMsg->message = DVL_WM_MOUSEMOVE; lpMsg->lParam = PositionForMouse(e.motion.x, e.motion.y); lpMsg->wParam = KeystateForMouse(0); - if (!sgbControllerActive && invflag) + if (ControlMode == ControlTypes::KeyboardAndMouse && invflag) InvalidateInventorySlot(); break; case SDL_MOUSEBUTTONDOWN: { diff --git a/Source/missiles.cpp b/Source/missiles.cpp index a417e8dfd..55ef3223d 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -8,6 +8,7 @@ #include #include "control.h" +#include "controls/plrctrls.h" #include "cursor.h" #include "dead.h" #ifdef _DEBUG @@ -2444,7 +2445,7 @@ void AddHealOther(Missile &missile, Point /*dst*/, Direction /*midir*/) UseMana(missile._misource, SPL_HEALOTHER); if (missile._misource == MyPlayerId) { NewCursor(CURSOR_HEALOTHER); - if (sgbControllerActive) + if (ControlMode != ControlTypes::KeyboardAndMouse) TryIconCurs(); } } @@ -2480,7 +2481,7 @@ void AddIdentify(Missile &missile, Point /*dst*/, Direction /*midir*/) sbookflag = false; if (!invflag) { invflag = true; - if (sgbControllerActive) + if (ControlMode != ControlTypes::KeyboardAndMouse) FocusOnInventory(); } NewCursor(CURSOR_IDENTIFY); @@ -2577,7 +2578,7 @@ void AddRepair(Missile &missile, Point /*dst*/, Direction /*midir*/) sbookflag = false; if (!invflag) { invflag = true; - if (sgbControllerActive) + if (ControlMode != ControlTypes::KeyboardAndMouse) FocusOnInventory(); } NewCursor(CURSOR_REPAIR); @@ -2593,7 +2594,7 @@ void AddRecharge(Missile &missile, Point /*dst*/, Direction /*midir*/) sbookflag = false; if (!invflag) { invflag = true; - if (sgbControllerActive) + if (ControlMode != ControlTypes::KeyboardAndMouse) FocusOnInventory(); } NewCursor(CURSOR_RECHARGE); @@ -2606,7 +2607,7 @@ void AddDisarm(Missile &missile, Point /*dst*/, Direction /*midir*/) UseMana(missile._misource, SPL_DISARM); if (missile._misource == MyPlayerId) { NewCursor(CURSOR_DISARM); - if (sgbControllerActive) { + if (ControlMode != ControlTypes::KeyboardAndMouse) { if (pcursobj != -1) NetSendCmdLocParam1(true, CMD_DISARMXY, cursPosition, pcursobj); else @@ -2703,7 +2704,7 @@ void AddResurrect(Missile &missile, Point /*dst*/, Direction /*midir*/) UseMana(missile._misource, SPL_RESURRECT); if (missile._misource == MyPlayerId) { NewCursor(CURSOR_RESURRECT); - if (sgbControllerActive) + if (ControlMode != ControlTypes::KeyboardAndMouse) TryIconCurs(); } missile._miDelFlag = true; diff --git a/Source/platform/vita/touch.cpp b/Source/platform/vita/touch.cpp index 58c20f713..a3e1fc848 100644 --- a/Source/platform/vita/touch.cpp +++ b/Source/platform/vita/touch.cpp @@ -1,14 +1,23 @@ +#include "platform/vita/touch.h" + #include +#include "miniwin/miniwin.h" #include "options.h" -#include "touch.h" #include "utils/display.h" #include "utils/ui_fwd.h" -static int visible_width; -static int visible_height; -static int x_borderwidth; -static int y_borderwidth; +namespace devilution { + +namespace { + +#define TOUCH_PORT_MAX_NUM 1 +#define NO_TOUCH (-1) // finger id setting if finger is not touching the screen + +int visible_width; +int visible_height; +int x_borderwidth; +int y_borderwidth; template inline T clip(T v, T amin, T amax) @@ -21,24 +30,20 @@ inline T clip(T v, T amin, T amax) return v; } -#define TOUCH_PORT_MAX_NUM 1 -#define NO_TOUCH (-1) // finger id setting if finger is not touching the screen +void SetMouseMotionEvent(SDL_Event *event, int32_t x, int32_t y, int32_t xrel, int32_t yrel) +{ + event->type = SDL_MOUSEMOTION; + event->motion.x = x; + event->motion.y = y; + event->motion.xrel = xrel; + event->motion.yrel = yrel; + event->motion.which = SDL_TOUCH_MOUSEID; +} -static void InitTouch(); -static void PreprocessEvents(SDL_Event *event); -static void PreprocessFingerDown(SDL_Event *event); -static void PreprocessFingerUp(SDL_Event *event); -static void preprocess_back_finger_down(SDL_Event *event); -static void preprocess_back_finger_up(SDL_Event *event); -static void PreprocessFingerMotion(SDL_Event *event); -static void SetMouseButtonEvent(SDL_Event *event, uint32_t type, uint8_t button, int32_t x, int32_t y); -static void SetMouseMotionEvent(SDL_Event *event, int32_t x, int32_t y, int32_t xrel, int32_t yrel); - -static bool touch_initialized = false; -static unsigned int simulated_click_start_time[TOUCH_PORT_MAX_NUM][2]; // initiation time of last simulated left or right click (zero if no click) -static bool direct_touch = true; // pointer jumps to finger -static int mouse_x = 0; // always reflects current mouse position -static int mouse_y = 0; +bool touch_initialized = false; +unsigned int simulated_click_start_time[TOUCH_PORT_MAX_NUM][2]; // initiation time of last simulated left or right click (zero if no click) +bool direct_touch = true; // pointer jumps to finger +Point Mouse; // always reflects current mouse position enum { // clang-format off @@ -58,7 +63,7 @@ struct Touch { float lastDownY; // SDL touch coordinates when last pressed down }; -static Touch finger[TOUCH_PORT_MAX_NUM][MaxNumFingers]; // keep track of finger status +Touch finger[TOUCH_PORT_MAX_NUM][MaxNumFingers]; // keep track of finger status enum DraggingType { DragNone, @@ -66,9 +71,9 @@ enum DraggingType { DragThreeFinger, }; -static DraggingType multi_finger_dragging[TOUCH_PORT_MAX_NUM]; // keep track whether we are currently drag-and-dropping +DraggingType multi_finger_dragging[TOUCH_PORT_MAX_NUM]; // keep track whether we are currently drag-and-dropping -static void InitTouch() +void InitTouch() { for (int port = 0; port < TOUCH_PORT_MAX_NUM; port++) { for (int i = 0; i < MaxNumFingers; i++) { @@ -91,56 +96,15 @@ static void InitTouch() y_borderwidth = (current.h - visible_height) / 2; } -static void PreprocessEvents(SDL_Event *event) -{ - // Supported touch gestures: - // left mouse click: single finger short tap - // right mouse click: second finger short tap while first finger is still down - // pointer motion: single finger drag - // left button drag and drop: dual finger drag - // right button drag and drop: triple finger drag - if (event->type != SDL_FINGERDOWN && event->type != SDL_FINGERUP && event->type != SDL_FINGERMOTION) { - return; - } - - // front (0) or back (1) panel - SDL_TouchID port = event->tfinger.touchId; - if (port != 0) { - if (devilution::sgOptions.Controller.bRearTouch) { - switch (event->type) { - case SDL_FINGERDOWN: - preprocess_back_finger_down(event); - break; - case SDL_FINGERUP: - preprocess_back_finger_up(event); - break; - } - } - return; - } - - switch (event->type) { - case SDL_FINGERDOWN: - PreprocessFingerDown(event); - break; - case SDL_FINGERUP: - PreprocessFingerUp(event); - break; - case SDL_FINGERMOTION: - PreprocessFingerMotion(event); - break; - } -} - -static void PreprocessFingerDown(SDL_Event *event) +void PreprocessFingerDown(SDL_Event *event) { // front (0) or back (1) panel SDL_TouchID port = event->tfinger.touchId; // id (for multitouch) SDL_FingerID id = event->tfinger.fingerId; - int x = mouse_x; - int y = mouse_y; + int x = Mouse.x; + int y = Mouse.y; if (direct_touch) { x = static_cast(event->tfinger.x * visible_width) + x_borderwidth; @@ -173,7 +137,7 @@ static void PreprocessFingerDown(SDL_Event *event) } } -static void preprocess_back_finger_down(SDL_Event *event) +void PreprocessBackFingerDown(SDL_Event *event) { // front (0) or back (1) panel SDL_TouchID port = event->tfinger.touchId; @@ -192,7 +156,7 @@ static void preprocess_back_finger_down(SDL_Event *event) } } -static void preprocess_back_finger_up(SDL_Event *event) +void PreprocessBackFingerUp(SDL_Event *event) { // front (0) or back (1) panel SDL_TouchID port = event->tfinger.touchId; @@ -204,14 +168,13 @@ static void preprocess_back_finger_up(SDL_Event *event) event->caxis.value = 0; event->caxis.which = 0; if (event->tfinger.x <= 0.5) { - ; event->caxis.axis = SDL_CONTROLLER_AXIS_TRIGGERLEFT; } else { event->caxis.axis = SDL_CONTROLLER_AXIS_TRIGGERRIGHT; } } -static void PreprocessFingerUp(SDL_Event *event) +void PreprocessFingerUp(SDL_Event *event) { // front (0) or back (1) panel SDL_TouchID port = event->tfinger.touchId; @@ -226,8 +189,8 @@ static void PreprocessFingerUp(SDL_Event *event) } } - int x = mouse_x; - int y = mouse_y; + int x = Mouse.x; + int y = Mouse.y; for (int i = 0; i < MaxNumFingers; i++) { if (finger[port][i].id != id) { @@ -268,7 +231,8 @@ static void PreprocessFingerUp(SDL_Event *event) devilution::OutputToLogical(&x, &y); } } - SetMouseButtonEvent(event, SDL_MOUSEBUTTONDOWN, simulatedButton, x, y); + SetMouseButtonEvent(*event, SDL_MOUSEBUTTONDOWN, simulatedButton, { x, y }); + event->button.which = SDL_TOUCH_MOUSEID; } else if (numFingersDown == 1) { // when dragging, and the last finger is lifted, the drag is over Uint8 simulatedButton = 0; @@ -277,13 +241,14 @@ static void PreprocessFingerUp(SDL_Event *event) } else { simulatedButton = SDL_BUTTON_LEFT; } - SetMouseButtonEvent(event, SDL_MOUSEBUTTONUP, simulatedButton, x, y); + SetMouseButtonEvent(*event, SDL_MOUSEBUTTONUP, simulatedButton, { x, y }); + event->button.which = SDL_TOUCH_MOUSEID; multi_finger_dragging[port] = DragNone; } } } -static void PreprocessFingerMotion(SDL_Event *event) +void PreprocessFingerMotion(SDL_Event *event) { // front (0) or back (1) panel SDL_TouchID port = event->tfinger.touchId; @@ -303,8 +268,8 @@ static void PreprocessFingerMotion(SDL_Event *event) } if (numFingersDown >= 1) { - int x = mouse_x; - int y = mouse_y; + int x = Mouse.x; + int y = Mouse.y; if (direct_touch) { x = static_cast(event->tfinger.x * visible_width) + x_borderwidth; @@ -316,14 +281,14 @@ static void PreprocessFingerMotion(SDL_Event *event) // convert touch events to relative mouse pointer events // Whenever an SDL_event involving the mouse is processed, - x = static_cast(mouse_x + (event->tfinger.dx * SpeedFactor * devilution::GetOutputSurface()->w)); - y = static_cast(mouse_y + (event->tfinger.dy * SpeedFactor * devilution::GetOutputSurface()->h)); + x = static_cast(Mouse.x + (event->tfinger.dx * SpeedFactor * devilution::GetOutputSurface()->w)); + y = static_cast(Mouse.y + (event->tfinger.dy * SpeedFactor * devilution::GetOutputSurface()->h)); } x = clip(x, 0, devilution::GetOutputSurface()->w); y = clip(y, 0, devilution::GetOutputSurface()->h); - int xrel = x - mouse_x; - int yrel = y - mouse_y; + int xrel = x - Mouse.x; + int yrel = y - Mouse.y; // update the current finger's coordinates so we can track it later for (int i = 0; i < MaxNumFingers; i++) { @@ -346,8 +311,7 @@ static void PreprocessFingerMotion(SDL_Event *event) } } if (numFingersDownlong >= 2) { - int mouseDownX = mouse_x; - int mouseDownY = mouse_y; + Point mouseDown = Mouse; if (direct_touch) { for (int i = 0; i < MaxNumFingers; i++) { if (finger[port][i].id == id) { @@ -355,8 +319,8 @@ static void PreprocessFingerMotion(SDL_Event *event) for (int j = 0; j < MaxNumFingers; j++) { if (finger[port][j].id >= 0 && (i != j)) { if (finger[port][j].timeLastDown < earliestTime) { - mouseDownX = finger[port][j].lastX; - mouseDownY = finger[port][j].lastY; + mouseDown.x = finger[port][j].lastX; + mouseDown.y = finger[port][j].lastY; earliestTime = finger[port][j].timeLastDown; } } @@ -375,7 +339,8 @@ static void PreprocessFingerMotion(SDL_Event *event) multi_finger_dragging[port] = DragThreeFinger; } SDL_Event ev; - SetMouseButtonEvent(&ev, SDL_MOUSEBUTTONDOWN, simulatedButton, mouseDownX, mouseDownY); + SetMouseButtonEvent(ev, SDL_MOUSEBUTTONDOWN, simulatedButton, mouseDown); + ev.button.which = SDL_TOUCH_MOUSEID; SDL_PushEvent(&ev); } } @@ -409,12 +374,52 @@ static void PreprocessFingerMotion(SDL_Event *event) } } -namespace devilution { +void PreprocessEvents(SDL_Event *event) +{ + // Supported touch gestures: + // left mouse click: single finger short tap + // right mouse click: second finger short tap while first finger is still down + // pointer motion: single finger drag + // left button drag and drop: dual finger drag + // right button drag and drop: triple finger drag + if (event->type != SDL_FINGERDOWN && event->type != SDL_FINGERUP && event->type != SDL_FINGERMOTION) { + return; + } -void handle_touch(SDL_Event *event, int currentMouseX, int currentMouseY) + // front (0) or back (1) panel + SDL_TouchID port = event->tfinger.touchId; + if (port != 0) { + if (devilution::sgOptions.Controller.bRearTouch) { + switch (event->type) { + case SDL_FINGERDOWN: + PreprocessBackFingerDown(event); + break; + case SDL_FINGERUP: + PreprocessBackFingerUp(event); + break; + } + } + return; + } + + switch (event->type) { + case SDL_FINGERDOWN: + PreprocessFingerDown(event); + break; + case SDL_FINGERUP: + PreprocessFingerUp(event); + break; + case SDL_FINGERMOTION: + PreprocessFingerMotion(event); + break; + } +} + +} // namespace + +void HandleTouchEvent(SDL_Event *event, Point mousePosition) { - mouse_x = currentMouseX; - mouse_y = currentMouseY; + Mouse = mousePosition; if (!touch_initialized) { InitTouch(); @@ -427,10 +432,9 @@ void handle_touch(SDL_Event *event, int currentMouseX, int currentMouseY) } } -void finish_simulated_mouse_clicks(int currentMouseX, int currentMouseY) +void FinishSimulatedMouseClicks(Point mousePosition) { - mouse_x = currentMouseX; - mouse_y = currentMouseY; + Mouse = mousePosition; for (auto &port : simulated_click_start_time) { for (int i = 0; i < 2; i++) { @@ -450,7 +454,8 @@ void finish_simulated_mouse_clicks(int currentMouseX, int currentMouseY) simulatedButton = SDL_BUTTON_RIGHT; } SDL_Event ev; - SetMouseButtonEvent(&ev, SDL_MOUSEBUTTONUP, simulatedButton, mouse_x, mouse_y); + SetMouseButtonEvent(ev, SDL_MOUSEBUTTONUP, simulatedButton, Mouse); + ev.button.which = SDL_TOUCH_MOUSEID; SDL_PushEvent(&ev); port[i] = 0; @@ -459,25 +464,3 @@ void finish_simulated_mouse_clicks(int currentMouseX, int currentMouseY) } } // namespace devilution - -static void SetMouseButtonEvent(SDL_Event *event, uint32_t type, uint8_t button, int32_t x, int32_t y) -{ - event->type = type; - event->button.button = button; - if (type == SDL_MOUSEBUTTONDOWN) { - event->button.state = SDL_PRESSED; - } else { - event->button.state = SDL_RELEASED; - } - event->button.x = x; - event->button.y = y; -} - -static void SetMouseMotionEvent(SDL_Event *event, int32_t x, int32_t y, int32_t xrel, int32_t yrel) -{ - event->type = SDL_MOUSEMOTION; - event->motion.x = x; - event->motion.y = y; - event->motion.xrel = xrel; - event->motion.yrel = yrel; -} diff --git a/Source/platform/vita/touch.h b/Source/platform/vita/touch.h index 6e96f0ea6..fff30d2a7 100644 --- a/Source/platform/vita/touch.h +++ b/Source/platform/vita/touch.h @@ -4,10 +4,12 @@ #include +#include "engine/point.hpp" + namespace devilution { -void handle_touch(SDL_Event *event, int currentMouseX, int currentMouseY); -void finish_simulated_mouse_clicks(int currentMouseX, int currentMouseY); +void HandleTouchEvent(SDL_Event *event, Point mousePosition); +void FinishSimulatedMouseClicks(Point mousePosition); } // namespace devilution diff --git a/Source/player.cpp b/Source/player.cpp index ff9f63df3..aeca966cd 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -7,6 +7,7 @@ #include #include "control.h" +#include "controls/plrctrls.h" #include "cursor.h" #include "dead.h" #ifdef _DEBUG @@ -2559,7 +2560,7 @@ void NextPlrLevel(int pnum) drawmanaflag = true; } - if (sgbControllerActive) + if (ControlMode != ControlTypes::KeyboardAndMouse) FocusOnCharInfo(); CalcPlrInv(player, true); @@ -3393,7 +3394,7 @@ void CheckPlrSpell(bool isShiftHeld, spell_id spellID, spell_type spellType) return; } - if (!sgbControllerActive) { + if (ControlMode == ControlTypes::KeyboardAndMouse) { if (pcurs != CURSOR_HAND) return; diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index ed0d23e3d..57b801420 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -6,6 +6,7 @@ #include "DiabloUI/ui_flags.hpp" #include "automap.h" +#include "controls/plrctrls.h" #include "controls/touch/renderers.h" #include "cursor.h" #include "dead.h" @@ -246,9 +247,7 @@ void UndrawCursor(const Surface &out) bool ShouldShowCursor() { - if (!sgbControllerActive && !sgbTouchActive) - return true; - if (IsMovingMouseCursorWithController()) + if (ControlMode == ControlTypes::KeyboardAndMouse) return true; if (pcurs == CURSOR_TELEPORT) return true; @@ -1274,12 +1273,10 @@ void DrawView(const Surface &out, Point startPosition) } else if (QuestLogIsOpen) { DrawQuestLog(out); } -#ifndef VIRTUAL_GAMEPAD - if (!chrflag && Players[MyPlayerId]._pStatPts != 0 && !spselflag + if (ControlMode != ControlTypes::VirtualGamepad && !chrflag && Players[MyPlayerId]._pStatPts != 0 && !spselflag && (!QuestLogIsOpen || !GetLeftPanel().Contains(GetMainPanel().position + Displacement { 0, -74 }))) { DrawLevelUpIcon(out); } -#endif if (ShowUniqueItemInfoBox) { DrawUniqueInfo(out); } diff --git a/Source/scrollrt.h b/Source/scrollrt.h index 4e44b3458..481345ead 100644 --- a/Source/scrollrt.h +++ b/Source/scrollrt.h @@ -25,11 +25,6 @@ enum class ScrollDirection : uint8_t { NorthWest, }; -// Defined in SourceX/controls/plctrls.cpp -extern bool sgbControllerActive; -extern bool sgbTouchActive; -extern bool IsMovingMouseCursorWithController(); - extern int LightTableIndex; extern uint32_t level_cel_block; extern char arch_draw_type; diff --git a/Source/trigs.cpp b/Source/trigs.cpp index e2637375d..a0056dd78 100644 --- a/Source/trigs.cpp +++ b/Source/trigs.cpp @@ -8,6 +8,7 @@ #include #include "control.h" +#include "controls/plrctrls.h" #include "cursor.h" #include "error.h" #include "init.h" @@ -749,7 +750,7 @@ void CheckTrigForce() { trigflag = false; - if (!sgbControllerActive && GetMainPanel().Contains(MousePosition)) { + if (ControlMode == ControlTypes::KeyboardAndMouse && GetMainPanel().Contains(MousePosition)) { return; } diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index 336540f1f..516e400e5 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -13,7 +13,9 @@ #include "DiabloUI/diabloui.h" #include "control.h" #include "controls/controller.h" +#ifndef USE_SDL1 #include "controls/devices/game_controller.h" +#endif #include "controls/devices/joystick.h" #include "controls/devices/kbcontroller.h" #include "controls/game_controls.h" @@ -186,6 +188,9 @@ bool SpawnWindow(const char *lpWindowName) #if SDL_VERSION_ATLEAST(2, 0, 10) SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); #endif +#if SDL_VERSION_ATLEAST(2, 0, 2) + SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); +#endif #if defined(_WIN32) && !defined(USE_SDL1) // The default WASAPI backend causes distortions @@ -405,14 +410,11 @@ void ResizeWindow() #ifndef USE_SDL1 SDL_SetWindowResizable(ghMainWnd, renderer != nullptr ? SDL_TRUE : SDL_FALSE); + InitializeVirtualGamepad(); #endif CreateBackBuffer(); force_redraw = 255; - -#ifdef VIRTUAL_GAMEPAD - InitializeVirtualGamepad(); -#endif } SDL_Surface *GetOutputSurface()