From ce5c1007a263e48d2db892455baf349a7c51fa98 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sun, 5 Jan 2020 09:22:48 +0000 Subject: [PATCH] Controller improvements: START modifier and hints 1. Makes START a modifier key. 2. Main modifier actions are now displayed as hints while the modifier is pressed. 3. Mouse simulation now available on all controllers: SELECT + D-Pad to move mouse SELECT + Left/Right should button to click START + | Action ---------- | ------ SELECT | Menu UP | Menu DOWN | Map LEFT | Character info RIGHT | Inventory B (Bottom) | Spell book Y (Left) | Quest log This makes all actions available on controllers without sticks and ZL/ZR. --- CMakeLists.txt | 1 + .../OpenDingux/devilutionx-retrofw.man.txt | 14 +- Source/control.cpp | 2 +- Source/control.h | 2 +- Source/scrollrt.cpp | 4 + SourceX/controls/controller_buttons.h | 8 ++ SourceX/controls/controller_motion.cpp | 28 +++- SourceX/controls/devices/kbcontroller.cpp | 66 +-------- SourceX/controls/game_controls.cpp | 104 +++++++++++--- SourceX/controls/game_controls.h | 3 + SourceX/controls/modifier_hints.cpp | 132 ++++++++++++++++++ SourceX/controls/modifier_hints.h | 7 + SourceX/controls/plrctrls.cpp | 5 +- 13 files changed, 286 insertions(+), 90 deletions(-) create mode 100644 SourceX/controls/modifier_hints.cpp create mode 100644 SourceX/controls/modifier_hints.h diff --git a/CMakeLists.txt b/CMakeLists.txt index be38349b6..06d0f72bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,6 +238,7 @@ set(devilutionx_SRCS SourceX/controls/controller_motion.cpp SourceX/controls/game_controls.cpp SourceX/controls/menu_controls.cpp + SourceX/controls/modifier_hints.cpp SourceX/controls/plrctrls.cpp SourceX/controls/touch.cpp SourceX/miniwin/ddraw.cpp diff --git a/Packaging/OpenDingux/devilutionx-retrofw.man.txt b/Packaging/OpenDingux/devilutionx-retrofw.man.txt index 6fc5727e1..ce75f1184 100644 --- a/Packaging/OpenDingux/devilutionx-retrofw.man.txt +++ b/Packaging/OpenDingux/devilutionx-retrofw.man.txt @@ -12,11 +12,13 @@ Controls: - Y: cast spell, delete character while in main menu - R1: use mana potion from belt - L1: use health item from belt -- Suspend: toggle automap -- Start: game menu, skip movie -- Select + R1: inventory -- Select + R2: character +- Start + Up: game menu +- Start + Left: character info +- Start + Right: inventory +- Start + Down: map - Select + A/B/X/Y: hot spell - Select + D-pad: move map/cursor -- Select + Suspend: left mouse click -- Select + Start: right mouse click +- Select + L1: left mouse click +- Select + R1: right mouse click +- Start + Select: game menu +- Suspend: map diff --git a/Source/control.cpp b/Source/control.cpp index 10b2f8222..648253abc 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1274,7 +1274,7 @@ void control_print_info_str(int y, char *str, BOOL center, int lines) } } -void PrintGameStr(int x, int y, char *str, int color) +void PrintGameStr(int x, int y, const char *str, int color) { BYTE c; int sx, sy; diff --git a/Source/control.h b/Source/control.h index ef91a8b33..acc494a80 100644 --- a/Source/control.h +++ b/Source/control.h @@ -85,7 +85,7 @@ BOOL control_WriteStringToBuffer(BYTE *str); void DrawInfoBox(); void control_draw_info_str(); void control_print_info_str(int y, char *str, BOOL center, int lines); -void PrintGameStr(int x, int y, char *str, int color); +void PrintGameStr(int x, int y, const char *str, int color); void DrawChr(); #define ADD_PlrStringXY(x, y, width, pszStr, col) MY_PlrStringXY(x, y, width, pszStr, col, 1) void MY_PlrStringXY(int x, int y, int width, char *pszStr, char col, int base); diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 7df9f370a..abc2d64df 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -872,6 +872,9 @@ static void DrawGame(int x, int y) } } +// DevilutionX extension. +extern void DrawControllerModifierHints(); + /** * @brief Start rendering of screen, town variation * @param StartX Center of view in dPiece coordinate @@ -926,6 +929,7 @@ void DrawView(int StartX, int StartY) gmenu_draw_pause(); } + DrawControllerModifierHints(); DrawPlrMsg(); gmenu_draw(); doom_draw(); diff --git a/SourceX/controls/controller_buttons.h b/SourceX/controls/controller_buttons.h index 3da3ad2c6..9e1405fa0 100644 --- a/SourceX/controls/controller_buttons.h +++ b/SourceX/controls/controller_buttons.h @@ -28,4 +28,12 @@ enum class ControllerButton { BUTTON_DPAD_RIGHT }; +inline bool IsDPadButton(ControllerButton button) +{ + return button == ControllerButton::BUTTON_DPAD_UP + || button == ControllerButton::BUTTON_DPAD_DOWN + || button == ControllerButton::BUTTON_DPAD_LEFT + || button == ControllerButton::BUTTON_DPAD_RIGHT; +} + } // namespace dvl diff --git a/SourceX/controls/controller_motion.cpp b/SourceX/controls/controller_motion.cpp index 8b9772d20..123d444a3 100644 --- a/SourceX/controls/controller_motion.cpp +++ b/SourceX/controls/controller_motion.cpp @@ -3,6 +3,7 @@ #include "controls/devices/game_controller.h" #include "controls/devices/joystick.h" #include "controls/devices/kbcontroller.h" +#include "controls/controller.h" namespace dvl { @@ -93,7 +94,32 @@ bool ProcessControllerMotion(const SDL_Event &event) if (ProcessKbCtrlAxisMotion(event)) return true; #endif - return false; + + // SELECT + D-Pad simulating mouse movement. + if (!IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) { + rightStickX = 0; + rightStickY = 0; + return false; + } + + const ControllerButtonEvent ctrl_event = ToControllerButtonEvent(event); + if (!IsDPadButton(ctrl_event.button)) + return false; + if (IsControllerButtonPressed(ControllerButton::BUTTON_DPAD_LEFT)) { + rightStickX = -1; + } else if (IsControllerButtonPressed(ControllerButton::BUTTON_DPAD_RIGHT)) { + rightStickX = 1; + } else { + rightStickX = 0; + } + if (IsControllerButtonPressed(ControllerButton::BUTTON_DPAD_UP)) { + rightStickY = 1; + } else if (IsControllerButtonPressed(ControllerButton::BUTTON_DPAD_DOWN)) { + rightStickY = -1; + } else { + rightStickY = 0; + } + return true; } } // namespace dvl diff --git a/SourceX/controls/devices/kbcontroller.cpp b/SourceX/controls/devices/kbcontroller.cpp index 992eb9acc..670444bc3 100644 --- a/SourceX/controls/devices/kbcontroller.cpp +++ b/SourceX/controls/devices/kbcontroller.cpp @@ -3,25 +3,11 @@ #if HAS_KBCTRL == 1 #include "controls/controller_motion.h" -#include "sdl2_to_1_2_backports.h" #include "sdl_compat.h" #include "stubs.h" namespace dvl { -namespace { - -bool IsModifierKey() -{ -#ifdef KBCTRL_BUTTON_BACK - return SDLC_GetKeyState()[KBCTRL_BUTTON_BACK]; -#else - return false; -#endif -} - -} // namespace - ControllerButton KbCtrlToControllerButton(const SDL_Event &event) { switch (event.type) { @@ -58,14 +44,10 @@ ControllerButton KbCtrlToControllerButton(const SDL_Event &event) #endif #ifdef KBCTRL_BUTTON_LEFTSHOULDER case KBCTRL_BUTTON_LEFTSHOULDER: - if (IsModifierKey()) - return ControllerButton::AXIS_TRIGGERLEFT; return ControllerButton::BUTTON_LEFTSHOULDER; #endif #ifdef KBCTRL_BUTTON_RIGHTSHOULDER case KBCTRL_BUTTON_RIGHTSHOULDER: - if (IsModifierKey()) - return ControllerButton::AXIS_TRIGGERRIGHT; return ControllerButton::BUTTON_RIGHTSHOULDER; #endif #ifdef KBCTRL_BUTTON_START @@ -78,26 +60,18 @@ ControllerButton KbCtrlToControllerButton(const SDL_Event &event) #endif #ifdef KBCTRL_BUTTON_DPAD_UP case KBCTRL_BUTTON_DPAD_UP: - if (IsModifierKey()) - return ControllerButton::IGNORE; return ControllerButton::BUTTON_DPAD_UP; #endif #ifdef KBCTRL_BUTTON_DPAD_DOWN case KBCTRL_BUTTON_DPAD_DOWN: - if (IsModifierKey()) - return ControllerButton::IGNORE; return ControllerButton::BUTTON_DPAD_DOWN; #endif #ifdef KBCTRL_BUTTON_DPAD_LEFT case KBCTRL_BUTTON_DPAD_LEFT: - if (IsModifierKey()) - return ControllerButton::IGNORE; return ControllerButton::BUTTON_DPAD_LEFT; #endif #ifdef KBCTRL_BUTTON_DPAD_RIGHT case KBCTRL_BUTTON_DPAD_RIGHT: - if (IsModifierKey()) - return ControllerButton::IGNORE; return ControllerButton::BUTTON_DPAD_RIGHT; #endif default: @@ -176,7 +150,9 @@ int ControllerButtonToKbCtrlKeyCode(ControllerButton button) } } -bool IsButtonPressed(ControllerButton button) +} // namespace + +bool IsKbCtrlButtonPressed(ControllerButton button) { int key_code = ControllerButtonToKbCtrlKeyCode(button); if (key_code == -1) @@ -188,42 +164,10 @@ bool IsButtonPressed(ControllerButton button) #endif } -} // namespace - -bool IsKbCtrlButtonPressed(ControllerButton button) -{ - if (IsModifierKey() && (button == ControllerButton::BUTTON_DPAD_UP || button == ControllerButton::BUTTON_DPAD_DOWN || button == ControllerButton::BUTTON_DPAD_LEFT || button == ControllerButton::BUTTON_DPAD_RIGHT)) - return false; - return IsButtonPressed(button); -} - bool ProcessKbCtrlAxisMotion(const SDL_Event &event) { - if (!IsModifierKey()) { - rightStickX = 0; - rightStickY = 0; - return false; - } - if (event.type != SDL_KEYUP && event.type != SDL_KEYDOWN) - return false; - const auto sym = event.key.keysym.sym; - if (sym != KBCTRL_BUTTON_DPAD_UP && sym != KBCTRL_BUTTON_DPAD_DOWN && sym != KBCTRL_BUTTON_DPAD_LEFT && sym != KBCTRL_BUTTON_DPAD_RIGHT) - return false; - if (IsButtonPressed(ControllerButton::BUTTON_DPAD_LEFT)) { - rightStickX = -1; - } else if (IsButtonPressed(ControllerButton::BUTTON_DPAD_RIGHT)) { - rightStickX = 1; - } else { - rightStickX = 0; - } - if (IsButtonPressed(ControllerButton::BUTTON_DPAD_UP)) { - rightStickY = 1; - } else if (IsButtonPressed(ControllerButton::BUTTON_DPAD_DOWN)) { - rightStickY = -1; - } else { - rightStickY = 0; - } - return true; + // Mapping keyboard to right stick axis not implemented. + return false; } } // namespace dvl diff --git a/SourceX/controls/game_controls.cpp b/SourceX/controls/game_controls.cpp index a8f26881c..4f7a45ea1 100644 --- a/SourceX/controls/game_controls.cpp +++ b/SourceX/controls/game_controls.cpp @@ -7,6 +7,7 @@ #include "controls/devices/game_controller.h" #include "controls/devices/joystick.h" #include "controls/menu_controls.h" +#include "controls/modifier_hints.h" #include "controls/plrctrls.h" namespace dvl { @@ -41,48 +42,113 @@ DWORD translate_controller_button_to_key(ControllerButton controller_button) } // namespace +bool start_modifier_active = false; +bool select_modifier_active = false; + bool GetGameAction(const SDL_Event &event, GameAction *action) { const ControllerButtonEvent ctrl_event = ToControllerButtonEvent(event); - if (!InGameMenu()) { + const bool in_game_menu = InGameMenu(); + + start_modifier_active = !in_game_menu && IsControllerButtonPressed(ControllerButton::BUTTON_START); + select_modifier_active = !in_game_menu && IsControllerButtonPressed(ControllerButton::BUTTON_BACK); + + // SELECT + D-Pad simulating mouse movement. + if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK) && IsDPadButton(ctrl_event.button)) { + return true; + } + + // START + SELECT + if (!ctrl_event.up + && ((ctrl_event.button == ControllerButton::BUTTON_BACK && IsControllerButtonPressed(ControllerButton::BUTTON_START)) + || (ctrl_event.button == ControllerButton::BUTTON_START && IsControllerButtonPressed(ControllerButton::BUTTON_BACK)))) { + select_modifier_active = start_modifier_active = false; + *action = GameActionSendKey{ DVL_VK_ESCAPE, ctrl_event.up }; + return true; + } + + if (!in_game_menu) { switch (ctrl_event.button) { + case ControllerButton::BUTTON_LEFTSHOULDER: + if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) { + *action = GameActionSendMouseClick{ GameActionSendMouseClick::LEFT, ctrl_event.up }; + return true; + } + break; + case ControllerButton::BUTTON_RIGHTSHOULDER: + if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) { + *action = GameActionSendMouseClick{ GameActionSendMouseClick::RIGHT, ctrl_event.up }; + return true; + } + break; case ControllerButton::AXIS_TRIGGERLEFT: // ZL (aka L2) if (!ctrl_event.up) { -#if HAS_KBCTRL == 0 if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) *action = GameAction(GameActionType::TOGGLE_QUEST_LOG); else -#endif *action = GameAction(GameActionType::TOGGLE_CHARACTER_INFO); } return true; case ControllerButton::AXIS_TRIGGERRIGHT: // ZR (aka R2) if (!ctrl_event.up) { -#if HAS_KBCTRL == 0 if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) *action = GameAction(GameActionType::TOGGLE_SPELL_BOOK); else -#endif *action = GameAction(GameActionType::TOGGLE_INVENTORY); } return true; -#if HAS_KBCTRL == 1 case ControllerButton::BUTTON_LEFTSTICK: if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) { - *action = GameActionSendMouseClick { GameActionSendMouseClick::LEFT, ctrl_event.up }; + *action = GameActionSendMouseClick{ GameActionSendMouseClick::LEFT, ctrl_event.up }; return true; } break; case ControllerButton::BUTTON_START: if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) { - *action = GameActionSendMouseClick { GameActionSendMouseClick::RIGHT, ctrl_event.up }; - return true; + *action = GameActionSendKey{ DVL_VK_ESCAPE, ctrl_event.up }; } + return true; break; -#endif default: break; } + if (IsControllerButtonPressed(ControllerButton::BUTTON_START)) { + switch (ctrl_event.button) { + case ControllerButton::IGNORE: + case ControllerButton::BUTTON_START: + return true; + case ControllerButton::BUTTON_DPAD_UP: + *action = GameActionSendKey{ DVL_VK_ESCAPE, ctrl_event.up }; + return true; + case ControllerButton::BUTTON_DPAD_RIGHT: + if (!ctrl_event.up) + *action = GameAction(GameActionType::TOGGLE_INVENTORY); + return true; + case ControllerButton::BUTTON_DPAD_DOWN: + *action = GameActionSendKey{ DVL_VK_TAB, ctrl_event.up }; + return true; + case ControllerButton::BUTTON_DPAD_LEFT: + if (!ctrl_event.up) + *action = GameAction(GameActionType::TOGGLE_CHARACTER_INFO); + return true; + case ControllerButton::BUTTON_Y: // Top button + // Not mapped. Reserved for future use. + return true; + case ControllerButton::BUTTON_B: // Right button + // Not mapped. TODO: map to attack in place. + return true; + case ControllerButton::BUTTON_A: // Bottom button + if (!ctrl_event.up) + *action = GameAction(GameActionType::TOGGLE_SPELL_BOOK); + return true; + case ControllerButton::BUTTON_X: // Left button + if (!ctrl_event.up) + *action = GameAction(GameActionType::TOGGLE_QUEST_LOG); + return true; + default: + return true; + } + } if (!questlog && !sbookflag) { switch (ctrl_event.button) { case ControllerButton::IGNORE: @@ -90,7 +156,7 @@ bool GetGameAction(const SDL_Event &event, GameAction *action) case ControllerButton::BUTTON_B: // Right button if (!ctrl_event.up) { if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) - *action = GameActionSendKey { DVL_VK_F8, ctrl_event.up }; + *action = GameActionSendKey{ DVL_VK_F8, ctrl_event.up }; else *action = GameAction(GameActionType::PRIMARY_ACTION); } @@ -98,7 +164,7 @@ bool GetGameAction(const SDL_Event &event, GameAction *action) case ControllerButton::BUTTON_Y: // Top button if (!ctrl_event.up) { if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) - *action = GameActionSendKey { DVL_VK_F6, ctrl_event.up }; + *action = GameActionSendKey{ DVL_VK_F6, ctrl_event.up }; else *action = GameAction(GameActionType::SECONDARY_ACTION); } @@ -106,7 +172,7 @@ bool GetGameAction(const SDL_Event &event, GameAction *action) case ControllerButton::BUTTON_X: // Left button if (!ctrl_event.up) { if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) - *action = GameActionSendKey { DVL_VK_F5, ctrl_event.up }; + *action = GameActionSendKey{ DVL_VK_F5, ctrl_event.up }; else *action = GameAction(GameActionType::CAST_SPELL); } @@ -114,7 +180,7 @@ bool GetGameAction(const SDL_Event &event, GameAction *action) case ControllerButton::BUTTON_A: // Bottom button if (!ctrl_event.up) { if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) - *action = GameActionSendKey { DVL_VK_F7, ctrl_event.up }; + *action = GameActionSendKey{ DVL_VK_F7, ctrl_event.up }; else *action = GameAction(GameActionType::TOGGLE_QUICK_SPELL_MENU); } @@ -131,13 +197,13 @@ bool GetGameAction(const SDL_Event &event, GameAction *action) case ControllerButton::BUTTON_DPAD_DOWN: case ControllerButton::BUTTON_DPAD_LEFT: case ControllerButton::BUTTON_DPAD_RIGHT: - // The rest is handled in charMovement() on every game_logic() call. + // The rest of D-Pad actions are handled in charMovement() on every game_logic() call. return true; case ControllerButton::BUTTON_RIGHTSTICK: if (IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) - *action = GameActionSendMouseClick { GameActionSendMouseClick::RIGHT, ctrl_event.up }; + *action = GameActionSendMouseClick{ GameActionSendMouseClick::RIGHT, ctrl_event.up }; else - *action = GameActionSendMouseClick { GameActionSendMouseClick::LEFT, ctrl_event.up }; + *action = GameActionSendMouseClick{ GameActionSendMouseClick::LEFT, ctrl_event.up }; return true; default: break; @@ -151,7 +217,7 @@ bool GetGameAction(const SDL_Event &event, GameAction *action) // By default, map to a keyboard key. if (ctrl_event.button != ControllerButton::NONE) { - *action = GameActionSendKey { translate_controller_button_to_key(ctrl_event.button), + *action = GameActionSendKey{ translate_controller_button_to_key(ctrl_event.button), ctrl_event.up }; return true; } @@ -174,7 +240,7 @@ MoveDirection GetMoveDirection() { const float stickX = leftStickX; const float stickY = leftStickY; - MoveDirection result { MoveDirectionX::NONE, MoveDirectionY::NONE }; + MoveDirection result{ MoveDirectionX::NONE, MoveDirectionY::NONE }; if (stickY >= 0.5 || IsControllerButtonPressed(ControllerButton::BUTTON_DPAD_UP)) { result.y = MoveDirectionY::UP; diff --git a/SourceX/controls/game_controls.h b/SourceX/controls/game_controls.h index b5fdcf4a3..7dfb8a941 100644 --- a/SourceX/controls/game_controls.h +++ b/SourceX/controls/game_controls.h @@ -83,4 +83,7 @@ struct MoveDirection { }; MoveDirection GetMoveDirection(); +extern bool start_modifier_active; +extern bool select_modifier_active; + } // namespace dvl diff --git a/SourceX/controls/modifier_hints.cpp b/SourceX/controls/modifier_hints.cpp new file mode 100644 index 000000000..ec990b101 --- /dev/null +++ b/SourceX/controls/modifier_hints.cpp @@ -0,0 +1,132 @@ +#include "controls/modifier_hints.h" + +#include + +#include "devilution.h" +#include "controls/controller.h" +#include "controls/game_controls.h" + +namespace dvl { + +namespace { + +int CalculateTextWidth(const char *s) +{ + int l = 0; + while (*s) { + l += fontkern[fontframe[gbFontTransTbl[static_cast(*s++)]]] + 1; + } + return l; +} + +int SpaceWidth() +{ + static const int kSpaceWidth = CalculateTextWidth(" "); + return kSpaceWidth; +} + +struct CircleMenuHint { + CircleMenuHint(bool is_dpad, const char *top, const char *right, const char *bottom, const char *left) + : is_dpad(is_dpad) + , top(top) + , top_w(CalculateTextWidth(top)) + , right(right) + , right_w(CalculateTextWidth(right)) + , bottom(bottom) + , bottom_w(CalculateTextWidth(bottom)) + , left(left) + , left_w(CalculateTextWidth(left)) + , x_mid(left_w + SpaceWidth() * 2.5) + { + } + + bool is_dpad; + + const char *top; + int top_w; + const char *right; + int right_w; + const char *bottom; + int bottom_w; + const char *left; + int left_w; + + int x_mid; +}; + +bool IsTopActive(const CircleMenuHint &hint) +{ + if (hint.is_dpad) + return IsControllerButtonPressed(ControllerButton::BUTTON_DPAD_UP); + return IsControllerButtonPressed(ControllerButton::BUTTON_Y); +} + +bool IsRightActive(const CircleMenuHint &hint) +{ + if (hint.is_dpad) + return IsControllerButtonPressed(ControllerButton::BUTTON_DPAD_RIGHT); + return IsControllerButtonPressed(ControllerButton::BUTTON_B); +} + +bool IsBottomActive(const CircleMenuHint &hint) +{ + if (hint.is_dpad) + return IsControllerButtonPressed(ControllerButton::BUTTON_DPAD_DOWN); + return IsControllerButtonPressed(ControllerButton::BUTTON_A); +} + +bool IsLeftActive(const CircleMenuHint &hint) +{ + if (hint.is_dpad) + return IsControllerButtonPressed(ControllerButton::BUTTON_DPAD_LEFT); + return IsControllerButtonPressed(ControllerButton::BUTTON_X); +} + +text_color CircleMenuHintTextColor(bool active) +{ + return active ? COL_BLUE : COL_GOLD; +} + +void DrawCircleMenuHint(const CircleMenuHint &hint, int x, int y) +{ + constexpr int kLineHeight = 25; + PrintGameStr(x + hint.x_mid - hint.top_w / 2, y, hint.top, CircleMenuHintTextColor(IsTopActive(hint))); + y += kLineHeight; + + PrintGameStr(x, y, hint.left, CircleMenuHintTextColor(IsLeftActive(hint))); + PrintGameStr(x + hint.left_w + 5 * SpaceWidth(), y, hint.right, CircleMenuHintTextColor(IsRightActive(hint))); + y += kLineHeight; + + PrintGameStr(x + hint.x_mid - hint.bottom_w / 2, y, hint.bottom, CircleMenuHintTextColor(IsBottomActive(hint))); +} + +constexpr int kCirclesDist = 200; +constexpr int kCirclesTop = VIEWPORT_HEIGHT / 2 + TILE_SIZE / 2; + +void DrawStartModifierMenu() +{ + if (!start_modifier_active) + return; + static const CircleMenuHint kDpad(/*is_dpad=*/true, /*top=*/"Menu", /*right=*/"Inv", /*bottom=*/"Map", /*left=*/"Char"); + static const CircleMenuHint kButtons(/*is_dpad=*/false, /*top=*/"", /*right=*/"", /*bottom=*/"Spells", /*left=*/"Quests"); + DrawCircleMenuHint(kDpad, SCREEN_WIDTH / 2 - kDpad.x_mid - kCirclesDist / 2, kCirclesTop); + DrawCircleMenuHint(kButtons, SCREEN_WIDTH / 2 - kButtons.x_mid + kCirclesDist / 2, kCirclesTop); +} + +void DrawSelectModifierMenu() +{ + if (!select_modifier_active) + return; + static const CircleMenuHint kSpells(/*is_dpad=*/false, "F6", "F8", "F7", "F5"); + DrawCircleMenuHint(kSpells, SCREEN_WIDTH / 2 - kSpells.x_mid + kCirclesDist / 2, kCirclesTop); +} + +} // namespace + +void DrawControllerModifierHints() +{ + DrawStartModifierMenu(); + DrawSelectModifierMenu(); +} + +} // namespace dvl diff --git a/SourceX/controls/modifier_hints.h b/SourceX/controls/modifier_hints.h new file mode 100644 index 000000000..0095d8ada --- /dev/null +++ b/SourceX/controls/modifier_hints.h @@ -0,0 +1,7 @@ +#pragma once + +namespace dvl { + +void DrawControllerModifierHints(); + +} // namespace dvl diff --git a/SourceX/controls/plrctrls.cpp b/SourceX/controls/plrctrls.cpp index 1e83f1696..e696965e0 100644 --- a/SourceX/controls/plrctrls.cpp +++ b/SourceX/controls/plrctrls.cpp @@ -4,6 +4,7 @@ #include #include +#include "controls/controller.h" #include "controls/controller_motion.h" #include "controls/game_controls.h" @@ -822,7 +823,9 @@ void WalkInDir(MoveDirection dir) void Movement() { - if (InGameMenu() || questlog) + if (InGameMenu() || questlog + || IsControllerButtonPressed(ControllerButton::BUTTON_START) + || IsControllerButtonPressed(ControllerButton::BUTTON_BACK)) return; MoveDirection move_dir = GetMoveDirection();