diff --git a/src/openrct2-ui/input/InputManager.cpp b/src/openrct2-ui/input/InputManager.cpp index 248b3d2672..173bd6f872 100644 --- a/src/openrct2-ui/input/InputManager.cpp +++ b/src/openrct2-ui/input/InputManager.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using namespace OpenRCT2::Ui; @@ -97,6 +98,7 @@ void InputManager::Process() CheckJoysticks(); HandleModifiers(); ProcessEvents(); + ProcessHoldEvents(); HandleViewScrolling(); } @@ -271,6 +273,105 @@ void InputManager::ProcessChat(const InputEvent& e) } } +void InputManager::ProcessHoldEvents() +{ + // Get mouse state + _mouseState = SDL_GetMouseState(nullptr, nullptr); + + // Get keyboard state + int numkeys; + auto keys = SDL_GetKeyboardState(&numkeys); + _keyboardState.resize(numkeys); + std::memcpy(_keyboardState.data(), keys, numkeys); + + // Check view scroll shortcuts + _viewScroll.x = 0; + _viewScroll.y = 0; + ProcessViewScrollEvent(ShortcutId::ScrollUp, { 0, -1 }); + ProcessViewScrollEvent(ShortcutId::ScrollDown, { 0, 1 }); + ProcessViewScrollEvent(ShortcutId::ScrollLeft, { -1, 0 }); + ProcessViewScrollEvent(ShortcutId::ScrollRight, { 1, 0 }); +} + +void InputManager::ProcessViewScrollEvent(std::string_view shortcutId, const ScreenCoordsXY& delta) +{ + auto& shortcutManager = GetShortcutManager(); + auto s = shortcutManager.GetShortcut(shortcutId); + if (s != nullptr && GetState(*s)) + { + _viewScroll.x += delta.x; + _viewScroll.y += delta.y; + } +} + +bool InputManager::GetState(const RegisteredShortcut& shortcut) const +{ + for (const auto& i : shortcut.Current) + { + if (GetState(i)) + { + return true; + } + } + return false; +} + +bool InputManager::GetState(const ShortcutInput& shortcut) const +{ + constexpr uint32_t UsefulModifiers = KMOD_SHIFT | KMOD_CTRL | KMOD_ALT | KMOD_GUI; + auto modifiers = SDL_GetModState() & UsefulModifiers; + if ((shortcut.Modifiers & UsefulModifiers) == modifiers) + { + switch (shortcut.Kind) + { + case InputDeviceKind::Mouse: + { + if (_mouseState & (1 << shortcut.Button)) + { + return true; + } + break; + } + case InputDeviceKind::Keyboard: + { + if (_keyboardState[shortcut.Button & 0xFF]) + { + return true; + } + break; + } + case InputDeviceKind::JoyButton: + { + for (auto* joystick : _joysticks) + { + if (SDL_JoystickGetButton(joystick, shortcut.Button)) + { + return true; + } + } + break; + } + case InputDeviceKind::JoyHat: + { + for (auto* joystick : _joysticks) + { + auto numHats = SDL_JoystickNumHats(joystick); + for (int i = 0; i < numHats; i++) + { + auto hat = SDL_JoystickGetHat(joystick, i); + if (hat & shortcut.Button) + { + return true; + } + } + } + break; + } + } + } + return false; +} + static InputManager _inputManager; InputManager& OpenRCT2::Ui::GetInputManager() diff --git a/src/openrct2-ui/input/InputManager.h b/src/openrct2-ui/input/InputManager.h index b5111e9e1f..1aa81ee225 100644 --- a/src/openrct2-ui/input/InputManager.h +++ b/src/openrct2-ui/input/InputManager.h @@ -18,6 +18,9 @@ typedef union SDL_Event SDL_Event; namespace OpenRCT2::Ui { + class RegisteredShortcut; + struct ShortcutInput; + enum class InputDeviceKind { Mouse, @@ -47,6 +50,8 @@ namespace OpenRCT2::Ui std::vector _joysticks; std::queue _events; ScreenCoordsXY _viewScroll; + uint32_t _mouseState; + std::vector _keyboardState; void CheckJoysticks(); @@ -56,6 +61,11 @@ namespace OpenRCT2::Ui void Process(const InputEvent& e); void ProcessInGameConsole(const InputEvent& e); void ProcessChat(const InputEvent& e); + void ProcessHoldEvents(); + void ProcessViewScrollEvent(std::string_view shortcutId, const ScreenCoordsXY& delta); + + bool GetState(const RegisteredShortcut& shortcut) const; + bool GetState(const ShortcutInput& shortcut) const; public: void QueueInputEvent(const SDL_Event& e);