From cf33230293004be048916574b94bdf3b8afa467c Mon Sep 17 00:00:00 2001 From: Nicholas Calaway Date: Tue, 16 Aug 2022 18:36:58 -0400 Subject: [PATCH] #3380 Use appropriate terms for mouse/gamepad/touch #5234 (#5235) --- Source/controls/devices/game_controller.cpp | 31 +++++ Source/controls/devices/game_controller.h | 2 + Source/controls/game_controls.h | 7 ++ Source/controls/plrctrls.cpp | 63 ++++++++-- Source/controls/plrctrls.h | 5 +- Source/items.cpp | 130 ++++++++++++-------- 6 files changed, 169 insertions(+), 69 deletions(-) diff --git a/Source/controls/devices/game_controller.cpp b/Source/controls/devices/game_controller.cpp index ec81982b4..3eb716163 100644 --- a/Source/controls/devices/game_controller.cpp +++ b/Source/controls/devices/game_controller.cpp @@ -232,4 +232,35 @@ bool GameController::IsPressedOnAnyController(ControllerButton button, SDL_Joyst return false; } +GamepadLayout GameController::getLayout(const SDL_Event &event) +{ +#if SDL_VERSION_ATLEAST(2, 0, 12) + const int index = event.cdevice.which; + const SDL_GameControllerType gamepadType = SDL_GameControllerTypeForIndex(index); + switch (gamepadType) { + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + return GamepadLayout::Nintendo; + case SDL_CONTROLLER_TYPE_PS3: + case SDL_CONTROLLER_TYPE_PS4: +#if SDL_VERSION_ATLEAST(2, 0, 14) + case SDL_CONTROLLER_TYPE_PS5: +#endif + return GamepadLayout::PlayStation; + case SDL_CONTROLLER_TYPE_XBOXONE: + case SDL_CONTROLLER_TYPE_XBOX360: +#if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + case SDL_CONTROLLER_TYPE_AMAZON_LUNA: +#endif + return GamepadLayout::Xbox; +#if SDL_VERSION_ATLEAST(2, 0, 14) + case SDL_CONTROLLER_TYPE_VIRTUAL: +#endif + case SDL_CONTROLLER_TYPE_UNKNOWN: + return GamepadLayout::Generic; + } +#endif + return GamepadLayout::Generic; +} + } // namespace devilution diff --git a/Source/controls/devices/game_controller.h b/Source/controls/devices/game_controller.h index 3c2a37941..f9ead4fe4 100644 --- a/Source/controls/devices/game_controller.h +++ b/Source/controls/devices/game_controller.h @@ -5,6 +5,7 @@ #include #include "controls/controller_buttons.h" +#include "controls/game_controls.h" namespace devilution { @@ -27,6 +28,7 @@ public: bool IsPressed(ControllerButton button) const; static bool ProcessAxisMotion(const SDL_Event &event); static SDL_GameControllerButton ToSdlGameControllerButton(ControllerButton button); + static GamepadLayout getLayout(const SDL_Event &event); private: SDL_GameController *sdl_game_controller_ = NULL; diff --git a/Source/controls/game_controls.h b/Source/controls/game_controls.h index 033b659f5..716ccca34 100644 --- a/Source/controls/game_controls.h +++ b/Source/controls/game_controls.h @@ -8,6 +8,13 @@ namespace devilution { +enum class GamepadLayout : uint8_t { + Generic, + Nintendo, + PlayStation, + Xbox, +}; + enum GameActionType : uint8_t { GameActionType_NONE, GameActionType_USE_HEALTH_POTION, diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index a52193052..0e2967998 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -46,6 +46,7 @@ namespace devilution { ControlTypes ControlMode = ControlTypes::None; ControlTypes ControlDevice = ControlTypes::None; ControllerButton ControllerButtonHeld = ControllerButton_NONE; +GamepadLayout GamepadType = GamepadLayout::Generic; int pcurstrig = -1; Missile *pcursmissile = nullptr; quest_id pcursquest = Q_INVALID; @@ -1464,6 +1465,21 @@ bool ContinueSimulatedMouseEvent(const SDL_Event &event, const ControllerButtonE return SimulatingMouseWithSelectAndDPad || IsSimulatedMouseClickBinding(gamepadEvent); } +string_view ControlTypeToString(ControlTypes controlType) +{ + switch (controlType) { + case ControlTypes::None: + return "None"; + case ControlTypes::KeyboardAndMouse: + return "KeyboardAndMouse"; + case ControlTypes::Gamepad: + return "Gamepad"; + case ControlTypes::VirtualGamepad: + return "VirtualGamepad"; + } + return "Invalid"; +} + void LogControlDeviceAndModeChange(ControlTypes newControlDevice, ControlTypes newControlMode) { if (SDL_LOG_PRIORITY_VERBOSE < SDL_LogGetPriority(SDL_LOG_CATEGORY_APPLICATION)) @@ -1478,23 +1494,37 @@ void LogControlDeviceAndModeChange(ControlTypes newControlDevice, ControlTypes n LogVerbose("Control: device {}, mode {}", DebugChange(ControlDevice, newControlDevice), DebugChange(ControlMode, newControlMode)); } -} // namespace - -string_view ControlTypeToString(ControlTypes controlType) -{ - switch (controlType) { - case ControlTypes::None: - return "None"; - case ControlTypes::KeyboardAndMouse: - return "KeyboardAndMouse"; - case ControlTypes::Gamepad: - return "Gamepad"; - case ControlTypes::VirtualGamepad: - return "VirtualGamepad"; +#ifndef USE_SDL1 +string_view GamepadTypeToString(GamepadLayout gamepadLayout) +{ + switch (gamepadLayout) { + case GamepadLayout::Nintendo: + return "Nintendo"; + case GamepadLayout::PlayStation: + return "PlayStation"; + case GamepadLayout::Xbox: + return "Xbox"; + case GamepadLayout::Generic: + return "Unknown"; } return "Invalid"; } +void LogGamepadChange(GamepadLayout newGamepad) +{ + if (SDL_LOG_PRIORITY_VERBOSE < SDL_LogGetPriority(SDL_LOG_CATEGORY_APPLICATION)) + return; + constexpr auto DebugChange = [](GamepadLayout before, GamepadLayout after) -> std::string { + if (before == after) + return std::string { GamepadTypeToString(before) }; + return StrCat(GamepadTypeToString(before), " -> ", GamepadTypeToString(after)); + }; + LogVerbose("Control: gamepad {}", DebugChange(GamepadType, newGamepad)); +} +#endif + +} // namespace + void DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent) { ControlTypes inputType = GetInputTypeFromEvent(event); @@ -1532,6 +1562,13 @@ void DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &game } else { ResetCursor(); } + if (ControlDevice == ControlTypes::Gamepad) { + GamepadLayout newGamepadLayout = GameController::getLayout(event); + if (newGamepadLayout != GamepadType) { + LogGamepadChange(newGamepadLayout); + GamepadType = newGamepadLayout; + } + } #endif } diff --git a/Source/controls/plrctrls.h b/Source/controls/plrctrls.h index 1db24b43c..29630c748 100644 --- a/Source/controls/plrctrls.h +++ b/Source/controls/plrctrls.h @@ -7,6 +7,7 @@ #include #include "controls/controller.h" +#include "controls/game_controls.h" #include "player.h" namespace devilution { @@ -23,8 +24,6 @@ enum class ControlTypes : uint8_t { VirtualGamepad, }; -string_view ControlTypeToString(ControlTypes controlType); - extern ControlTypes ControlMode; /** @@ -39,6 +38,8 @@ extern ControlTypes ControlDevice; extern ControllerButton ControllerButtonHeld; +extern GamepadLayout GamepadType; + // Runs every frame. // Handles menu movement. void plrctrls_every_frame(); diff --git a/Source/items.cpp b/Source/items.cpp index c9fc447a2..6cf602392 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1741,76 +1741,98 @@ void DrawUniqueInfoWindow(const Surface &out) DrawHalfTransparentRectTo(out, GetRightPanel().position.x - SidePanelSize.width + 27, GetRightPanel().position.y + 28, 265, 297); } -void PrintItemMisc(const Item &item) +void printItemMiscKBM(const Item &item, const bool isOil, const bool isCastOnTarget) { - if (item._iMiscId == IMISC_SCROLL) { - if (ControlMode == ControlTypes::KeyboardAndMouse) { - if (item._iSpell == SPL_TOWN || item._iSpell == SPL_IDENTIFY) { - AddPanelString(_("Right-click to read, then")); - AddPanelString(_("left-click to target")); - } else { - AddPanelString(_("Right-click to read")); - } - } else { - if (!invflag) { - AddPanelString(_("Open inventory to use")); - } else { - AddPanelString(_("Activate to read")); - } - } - } - if (item._iMiscId == IMISC_SCROLLT) { - if (ControlMode == ControlTypes::KeyboardAndMouse) { - if (item._iSpell == SPL_FLASH) { - AddPanelString(_("Right-click to read")); - } else { - AddPanelString(_("Right-click to read, then")); - AddPanelString(_("left-click to target")); - } - } else { - if (TargetsMonster(item._iSpell)) { - AddPanelString(_("Select from spell book, then")); - AddPanelString(_("cast spell to read")); - } else if (!invflag) { - AddPanelString(_("Open inventory to use")); - } else { - AddPanelString(_("Activate to read")); - } - } + if (item._iMiscId == IMISC_MAPOFDOOM) { + AddPanelString(_("Right-click to view")); + + } else if (isOil) { + PrintItemOil(item._iMiscId); + AddPanelString(_("Right-click to use")); + } else if (isCastOnTarget) { + AddPanelString(_("Right-click to read, then")); + AddPanelString(_("left-click to target")); + } else if (IsAnyOf(item._iMiscId, IMISC_BOOK, IMISC_NOTE, IMISC_SCROLL)) { + AddPanelString(_("Right-click to read")); } - if ((item._iMiscId >= IMISC_USEFIRST && item._iMiscId <= IMISC_USELAST) - || (item._iMiscId > IMISC_OILFIRST && item._iMiscId < IMISC_OILLAST) - || (item._iMiscId > IMISC_RUNEFIRST && item._iMiscId < IMISC_RUNELAST)) { +} + +void printItemMiscVirtualGamepad(const Item &item, const bool isOil) +{ + if (item._iMiscId == IMISC_MAPOFDOOM) { + AddPanelString(_("Activate to view")); + } else if (isOil) { PrintItemOil(item._iMiscId); - if (ControlMode == ControlTypes::KeyboardAndMouse) { - AddPanelString(_("Right-click to use")); + if (!invflag) { + AddPanelString(_("Open inventory to use")); + } else { - if (!invflag) { - AddPanelString(_("Open inventory to use")); - } else { - AddPanelString(_("Activate to use")); - } + AddPanelString(_("Activate to use")); } + } else if (item._iMiscId == IMISC_SCROLL) { + AddPanelString(_("Select from spell book, then")); + AddPanelString(_("cast to read")); + } else { + AddPanelString(_("Activate to read")); } - if (IsAnyOf(item._iMiscId, IMISC_BOOK, IMISC_NOTE)) { - if (ControlMode == ControlTypes::KeyboardAndMouse) { - AddPanelString(_("Right-click to read")); - } else { - AddPanelString(_("Activate to read")); - } +} + +void printItemMiscGamepad(const Item &item, bool isOil, bool isCastOnTarget) +{ + std::string activateButton = "Activate"; + std::string castButton = "Cast"; + + if (GamepadType == GamepadLayout::Xbox) { + activateButton = "Y"; + castButton = "X"; + } else if (GamepadType == GamepadLayout::PlayStation) { + activateButton = "Triangle"; + castButton = "Square"; + } else if (GamepadType == GamepadLayout::Nintendo) { + activateButton = "Y"; + castButton = "X"; } + if (item._iMiscId == IMISC_MAPOFDOOM) { - if (ControlMode == ControlTypes::KeyboardAndMouse) { - AddPanelString(_("Right-click to view")); + AddPanelString(fmt::format(fmt::runtime(_("{} to view")), activateButton)); + } else if (isOil) { + PrintItemOil(item._iMiscId); + if (!invflag) { + AddPanelString(_("Open inventory to use")); } else { - AddPanelString(_("Activate to view")); + AddPanelString(fmt::format(fmt::runtime(_("{} to use")), activateButton)); } + } else if (isCastOnTarget) { + AddPanelString(fmt::format(fmt::runtime(_("Select from spell book, then {} to read")), castButton)); + } else if (IsAnyOf(item._iMiscId, IMISC_BOOK, IMISC_NOTE, IMISC_SCROLL)) { + AddPanelString(fmt::format(fmt::runtime(_("{} to read")), activateButton)); } +} + +void PrintItemMisc(const Item &item) +{ if (item._iMiscId == IMISC_EAR) { AddPanelString(fmt::format(fmt::runtime(pgettext("player", "Level: {:d}")), item._ivalue)); + return; } if (item._iMiscId == IMISC_AURIC) { AddPanelString(_("Doubles gold capacity")); + return; + } + const bool isOil = (item._iMiscId >= IMISC_USEFIRST && item._iMiscId <= IMISC_USELAST) + || (item._iMiscId > IMISC_OILFIRST && item._iMiscId < IMISC_OILLAST) + || (item._iMiscId > IMISC_RUNEFIRST && item._iMiscId < IMISC_RUNELAST); + const bool isCastOnTarget = (item._iMiscId == IMISC_SCROLLT && item._iSpell != SPL_FLASH) + || item._iSpell == SPL_TOWN + || item._iSpell == SPL_IDENTIFY + || TargetsMonster(item._iSpell); + + if (ControlMode == ControlTypes::KeyboardAndMouse) { + printItemMiscKBM(item, isOil, isCastOnTarget); + } else if (ControlMode == ControlTypes::VirtualGamepad) { + printItemMiscVirtualGamepad(item, isOil); + } else { + printItemMiscGamepad(item, isOil, isCastOnTarget); } }