Add input manager

This commit is contained in:
Ted John 2020-12-13 03:40:10 +00:00
parent b1eb975529
commit ccae533978
8 changed files with 210 additions and 0 deletions

View File

@ -26,6 +26,7 @@
#include <cmath>
#include <cstdlib>
#include <memory>
#include <openrct2-ui/input/InputManager.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/Context.h>
#include <openrct2/Input.h>
@ -415,6 +416,15 @@ public:
break;
}
_cursorState.touch = false;
{
InputEvent ie;
ie.DeviceKind = InputDeviceKind::Mouse;
ie.Button = e.button.button;
ie.State = InputEventState::Down;
auto& inputManager = GetInputManager();
inputManager.QueueInputEvent(std::move(ie));
}
break;
}
case SDL_MOUSEBUTTONUP:
@ -442,6 +452,15 @@ public:
break;
}
_cursorState.touch = false;
{
InputEvent ie;
ie.DeviceKind = InputDeviceKind::Mouse;
ie.Button = e.button.button;
ie.State = InputEventState::Release;
auto& inputManager = GetInputManager();
inputManager.QueueInputEvent(std::move(ie));
}
break;
}
// Apple sends touchscreen events for trackpads, so ignore these events on macOS

View File

@ -14,6 +14,7 @@
#include "interface/Theme.h"
#include "windows/Window.h"
#include <openrct2-ui/input/InputManager.h>
#include <openrct2-ui/windows/Window.h>
#include <openrct2/Input.h>
#include <openrct2/config/Config.h>
@ -517,6 +518,9 @@ public:
void HandleKeyboard(bool isTitle) override
{
InputHandleKeyboard(isTitle);
auto& inputManager = GetInputManager();
inputManager.Process();
}
std::string GetKeyboardShortcutString(int32_t shortcut) override

View File

@ -0,0 +1,42 @@
/*****************************************************************************
* Copyright (c) 2014-2020 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "InputManager.h"
#include <openrct2-ui/input/ShortcutManager.h>
using namespace OpenRCT2::Ui;
void InputManager::QueueInputEvent(InputEvent&& e)
{
_events.push(e);
}
void InputManager::Process()
{
while (!_events.empty())
{
const auto& e = _events.front();
Process(e);
_events.pop();
}
}
void InputManager::Process(const InputEvent& e)
{
auto& shortcutManager = GetShortcutManager();
shortcutManager.ProcessEvent(e);
}
static InputManager _inputManager;
InputManager& OpenRCT2::Ui::GetInputManager()
{
return _inputManager;
}

View File

@ -0,0 +1,50 @@
/*****************************************************************************
* Copyright (c) 2014-2020 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include <queue>
namespace OpenRCT2::Ui
{
enum class InputDeviceKind
{
Mouse,
Keyboard,
Gamepad,
};
enum class InputEventState
{
Down,
Release,
};
struct InputEvent
{
InputDeviceKind DeviceKind;
uint32_t Button;
InputEventState State;
};
class InputManager
{
private:
std::queue<InputEvent> _events;
void Process(const InputEvent& e);
public:
void QueueInputEvent(InputEvent&& e);
void Process();
};
InputManager& GetInputManager();
} // namespace OpenRCT2::Ui

View File

@ -11,6 +11,7 @@
#include <SDL.h>
#include <openrct2/core/String.hpp>
#include <openrct2/interface/Window.h>
#include <openrct2/localisation/Language.h>
using namespace OpenRCT2::Ui;
@ -214,6 +215,30 @@ bool ShortcutInput::AppendModifier(std::string& s, const std::string_view& text,
return false;
}
bool ShortcutInput::Matches(const InputEvent& e) const
{
if (e.DeviceKind == InputDeviceKind::Mouse)
{
if (Kind == ShortcutInputKind::Mouse && Key == e.Button)
{
return true;
}
}
return false;
}
std::optional<ShortcutInput> ShortcutInput::FromInputEvent(const InputEvent& e)
{
if (e.DeviceKind == InputDeviceKind::Mouse)
{
ShortcutInput result;
result.Kind = ShortcutInputKind::Mouse;
result.Key = e.Button;
return result;
}
return {};
}
std::string_view RegisteredShortcut::GetGroup() const
{
auto fullstopIndex = Id.find('.');
@ -242,6 +267,53 @@ RegisteredShortcut* ShortcutManager::GetShortcut(std::string_view id)
void ShortcutManager::SetPendingShortcutChange(std::string_view id)
{
_pendingShortcutChange = id;
}
bool ShortcutManager::IsSuitableInputEvent(const InputEvent& e)
{
if (e.DeviceKind == InputDeviceKind::Mouse)
{
// Do not allow LMB or RMB to be shortcut
if (e.Button == 0 || e.Button == 1)
{
return false;
}
}
return true;
}
void ShortcutManager::ProcessEvent(const InputEvent& e)
{
if (_pendingShortcutChange.empty())
{
for (const auto& shortcut : Shortcuts)
{
for (const auto& action : shortcut.Current)
{
if (action.Matches(e))
{
shortcut.Action();
break;
}
}
}
}
else if (IsSuitableInputEvent(e))
{
auto shortcut = GetShortcut(_pendingShortcutChange);
if (shortcut != nullptr)
{
auto shortcutInput = ShortcutInput::FromInputEvent(e);
if (shortcutInput)
{
shortcut->Current.clear();
shortcut->Current.push_back(std::move(*shortcutInput));
}
}
_pendingShortcutChange.clear();
window_close_by_class(WC_CHANGE_KEYBOARD_SHORTCUT);
}
}
static ShortcutManager _shortcutManager;

View File

@ -9,9 +9,12 @@
#pragma once
#include "InputManager.h"
#include <cstdint>
#include <functional>
#include <openrct2/localisation/StringIds.h>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
@ -35,6 +38,10 @@ namespace OpenRCT2::Ui
ShortcutInput(const std::string_view& value);
std::string ToString() const;
bool Matches(const InputEvent& e) const;
static std::optional<ShortcutInput> FromInputEvent(const InputEvent& e);
private:
bool AppendModifier(std::string& s, const std::string_view& text, uint32_t left, uint32_t right) const;
};
@ -78,6 +85,11 @@ namespace OpenRCT2::Ui
class ShortcutManager
{
private:
std::string _pendingShortcutChange;
static bool IsSuitableInputEvent(const InputEvent& e);
public:
std::vector<RegisteredShortcut> Shortcuts;
@ -88,6 +100,7 @@ namespace OpenRCT2::Ui
void RegisterDefaultShortcuts();
RegisteredShortcut* GetShortcut(std::string_view id);
void SetPendingShortcutChange(std::string_view id);
void ProcessEvent(const InputEvent& e);
};
ShortcutManager& GetShortcutManager();

View File

@ -41,6 +41,7 @@
<ClInclude Include="drawing\engines\opengl\TextureCache.h" />
<ClInclude Include="drawing\engines\opengl\TransparencyDepth.h" />
<ClInclude Include="input\Input.h" />
<ClInclude Include="input\InputManager.h" />
<ClInclude Include="input\KeyboardShortcuts.h" />
<ClInclude Include="input\ShortcutManager.h" />
<ClInclude Include="interface\Dropdown.h" />
@ -92,6 +93,7 @@
<ClCompile Include="drawing\engines\opengl\TransparencyDepth.cpp" />
<ClCompile Include="drawing\engines\SoftwareDrawingEngine.cpp" />
<ClCompile Include="input\Input.cpp" />
<ClCompile Include="input\InputManager.cpp" />
<ClCompile Include="input\KeyboardShortcut.cpp" />
<ClCompile Include="input\KeyboardShortcuts.cpp" />
<ClCompile Include="input\MouseInput.cpp" />

View File

@ -35,12 +35,14 @@ static rct_widget window_shortcut_change_widgets[] = {
{ WIDGETS_END }
};
static void window_shortcut_change_close(rct_window *w);
static void window_shortcut_change_mouseup(rct_window *w, rct_widgetindex widgetIndex);
static void window_shortcut_change_paint(rct_window *w, rct_drawpixelinfo *dpi);
// 0x9A3F7C
static rct_window_event_list window_shortcut_change_events([](auto& events)
{
events.close = &window_shortcut_change_close;
events.mouse_up = &window_shortcut_change_mouseup;
events.paint = &window_shortcut_change_paint;
});
@ -72,6 +74,12 @@ rct_window* window_shortcut_change_open(const std::string_view& shortcutId)
}
}
static void window_shortcut_change_close(rct_window* w)
{
auto& shortcutManager = GetShortcutManager();
shortcutManager.SetPendingShortcutChange({});
}
/**
*
* rct2: 0x006E3AE0