-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathGUIInputWrapper.cpp
More file actions
182 lines (156 loc) · 7.38 KB
/
GUIInputWrapper.cpp
File metadata and controls
182 lines (156 loc) · 7.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include "GUI.h"
#include "GUIInputWrapper.h"
#include "SDL3/SDL.h"
#include "WindowMan.h"
#include "FrameMan.h"
#include "UInputMan.h"
#include "Timer.h"
#include <SDL3/SDL.h>
#include <iostream>
using namespace RTE;
GUIInputWrapper::GUIInputWrapper(int whichPlayer, bool keyJoyMouseCursor) :
GUIInput(whichPlayer, keyJoyMouseCursor) {
m_KeyTimer = std::make_unique<Timer>();
m_CursorAccelTimer = std::make_unique<Timer>();
memset(m_KeyboardBuffer, 0, sizeof(uint8_t) * GUIInput::Constants::KEYBOARD_BUFFER_SIZE);
memset(m_ScanCodeState, 0, sizeof(uint8_t) * GUIInput::Constants::KEYBOARD_BUFFER_SIZE);
m_KeyHoldDuration.fill(-1);
}
void GUIInputWrapper::ConvertKeyEvent(SDL_Scancode sdlKey, int guilibKey, float elapsedS) {
int nKeys;
const bool* sdlKeyState = SDL_GetKeyboardState(&nKeys);
if (sdlKeyState[sdlKey]) {
if (m_KeyHoldDuration[guilibKey] < 0) {
m_KeyboardBuffer[guilibKey] = GUIInput::Pushed;
m_KeyHoldDuration[guilibKey] = 0;
} else if (m_KeyHoldDuration[guilibKey] < m_KeyRepeatDelay) {
m_KeyboardBuffer[guilibKey] = GUIInput::None;
} else {
m_KeyboardBuffer[guilibKey] = GUIInput::Repeat;
m_KeyHoldDuration[guilibKey] = 0;
}
m_KeyHoldDuration[guilibKey] += elapsedS;
} else {
if (m_KeyHoldDuration[guilibKey] >= 0) {
m_KeyboardBuffer[guilibKey] = GUIInput::Released;
} else {
m_KeyboardBuffer[guilibKey] = GUIInput::None;
}
m_KeyHoldDuration[guilibKey] = -1;
}
}
void GUIInputWrapper::Update() {
float keyElapsedTime = static_cast<float>(m_KeyTimer->GetElapsedRealTimeS());
m_KeyTimer->Reset();
UpdateKeyboardInput(keyElapsedTime);
UpdateMouseInput();
// If joysticks and keyboard can control the mouse cursor too.
if (m_KeyJoyMouseCursor) {
UpdateKeyJoyMouseInput(keyElapsedTime);
}
// Update the mouse position of this GUIInput, based on the SDL mouse vars (which may have been altered by joystick or keyboard input).
Vector mousePos = g_UInputMan.GetAbsoluteMousePosition(m_Player);
m_MouseX = static_cast<int>(mousePos.GetX() / static_cast<float>(g_WindowMan.GetResMultiplier()));
m_MouseY = static_cast<int>(mousePos.GetY() / static_cast<float>(g_WindowMan.GetResMultiplier()));
}
void GUIInputWrapper::StartTextInput() {
GUIInput::StartTextInput();
SDL_StartTextInput(g_WindowMan.GetWindow());
}
void GUIInputWrapper::StopTextInput() {
GUIInput::StopTextInput();
if (m_TextInputActive <= 0) {
SDL_StopTextInput(g_WindowMan.GetWindow());
}
}
void GUIInputWrapper::UpdateKeyboardInput(float keyElapsedTime) {
// Clear the keyboard buffer, we need it to check for changes.
memset(m_KeyboardBuffer, 0, sizeof(uint8_t) * GUIInput::Constants::KEYBOARD_BUFFER_SIZE);
memset(m_ScanCodeState, 0, sizeof(uint8_t) * GUIInput::Constants::KEYBOARD_BUFFER_SIZE);
for (size_t k = 0; k < GUIInput::Constants::KEYBOARD_BUFFER_SIZE; ++k) {
if (g_UInputMan.KeyPressed(static_cast<SDL_Scancode>(k))) {
m_ScanCodeState[k] = GUIInput::Pushed;
uint8_t keyName = static_cast<uint8_t>(SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(k), NULL, false));
m_KeyboardBuffer[keyName] = GUIInput::Pushed;
}
}
m_HasTextInput = g_UInputMan.GetTextInput(m_TextInput);
ConvertKeyEvent(SDL_SCANCODE_SPACE, ' ', keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_BACKSPACE, GUIInput::Key_Backspace, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_TAB, GUIInput::Key_Tab, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_RETURN, GUIInput::Key_Enter, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_KP_ENTER, GUIInput::Key_Enter, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_ESCAPE, GUIInput::Key_Escape, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_LEFT, GUIInput::Key_LeftArrow, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_RIGHT, GUIInput::Key_RightArrow, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_UP, GUIInput::Key_UpArrow, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_DOWN, GUIInput::Key_DownArrow, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_INSERT, GUIInput::Key_Insert, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_DELETE, GUIInput::Key_Delete, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_HOME, GUIInput::Key_Home, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_END, GUIInput::Key_End, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_PAGEUP, GUIInput::Key_PageUp, keyElapsedTime);
ConvertKeyEvent(SDL_SCANCODE_PAGEDOWN, GUIInput::Key_PageDown, keyElapsedTime);
m_Modifier = GUIInput::ModNone;
SDL_Keymod keyShifts = SDL_GetModState();
if (keyShifts & SDL_KMOD_SHIFT) {
m_Modifier |= GUIInput::ModShift;
}
if (keyShifts & SDL_KMOD_ALT) {
m_Modifier |= GUIInput::ModAlt;
}
if (keyShifts & SDL_KMOD_CTRL) {
m_Modifier |= GUIInput::ModCtrl;
}
if (keyShifts & SDL_KMOD_GUI) {
m_Modifier |= GUIInput::ModCommand;
}
}
void GUIInputWrapper::UpdateMouseInput() {
const auto& buttonStates = g_UInputMan.GetMouseState(m_Player);
const auto& buttonChange = g_UInputMan.GetMouseChange(m_Player);
Vector mousePos = g_UInputMan.GetAbsoluteMousePosition(m_Player);
m_MouseX = mousePos.GetFloorIntX();
m_MouseY = mousePos.GetFloorIntY();
for (int button = 0; button < 3; button++) {
m_MouseButtonsStates[button] = buttonStates[button + 1] ? Down : Up;
if (m_MouseButtonsStates[button] == Down) {
m_MouseButtonsEvents[button] = buttonChange[button + 1] ? Pushed : Repeat;
} else {
m_MouseButtonsEvents[button] = buttonChange[button + 1] ? Released : None;
}
}
}
void GUIInputWrapper::UpdateKeyJoyMouseInput(float keyElapsedTime) {
// TODO Try to not use magic numbers throughout this method.
float mouseDenominator = g_WindowMan.GetResMultiplier();
Vector joyKeyDirectional = g_UInputMan.GetMenuDirectional() * 5;
// See how much to accelerate the joystick input based on how long the stick has been pushed around.
if (joyKeyDirectional.MagnitudeIsLessThan(0.95F)) {
m_CursorAccelTimer->Reset();
}
float acceleration = 0.25F + static_cast<float>(std::min(m_CursorAccelTimer->GetElapsedRealTimeS(), 0.5)) * 20.0F;
Vector newMousePos = g_UInputMan.GetAbsoluteMousePosition(m_Player);
// Manipulate the mouse position with the joysticks or keys.
newMousePos.m_X += joyKeyDirectional.GetX() * static_cast<float>(mouseDenominator) * keyElapsedTime * 15.0F * acceleration;
newMousePos.m_Y += joyKeyDirectional.GetY() * static_cast<float>(mouseDenominator) * keyElapsedTime * 15.0F * acceleration;
// Keep the mouse within the bounds of the screen. Give it a bit of leeway on the right side, to account for the cursor sprite size.
newMousePos.m_X = std::clamp(newMousePos.m_X, 0.0F, static_cast<float>(g_WindowMan.GetResX() * mouseDenominator) - 3.0F);
newMousePos.m_Y = std::clamp(newMousePos.m_Y, 0.0F, static_cast<float>(g_WindowMan.GetResY() * mouseDenominator) - 3.0F);
g_UInputMan.SetAbsoluteMousePosition(newMousePos, m_Player);
// Update mouse button states and presses. In the menu, either left or mouse button works.
if (g_UInputMan.MenuButtonHeld(UInputMan::MenuCursorButtons::MENU_EITHER)) {
m_MouseButtonsStates[0] = GUIInput::Down;
m_MouseButtonsEvents[0] = GUIInput::Repeat;
}
if (g_UInputMan.MenuButtonPressed(UInputMan::MenuCursorButtons::MENU_EITHER)) {
m_MouseButtonsStates[0] = GUIInput::Down;
m_MouseButtonsEvents[0] = GUIInput::Pushed;
} else if (g_UInputMan.MenuButtonReleased(UInputMan::MenuCursorButtons::MENU_EITHER)) {
m_MouseButtonsStates[0] = GUIInput::Up;
m_MouseButtonsEvents[0] = GUIInput::Released;
} else if (m_MouseButtonsEvents[0] == GUIInput::Released) {
m_MouseButtonsStates[0] = GUIInput::Up;
m_MouseButtonsEvents[0] = GUIInput::None;
}
}