Skip to content

Commit b410c9c

Browse files
authored
Merge pull request #206 from cortex-command-community/joystick-fixes
Fix Menu cursor and Gamepad
2 parents 23836d1 + 3b43130 commit b410c9c

File tree

4 files changed

+49
-54
lines changed

4 files changed

+49
-54
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
compile_commands.json
1414
**/.ccls-cache
1515
**/.cache
16+
**/.clangd
17+
1618

1719
**/build*
1820

Source/Managers/UInputMan.cpp

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,9 @@ UInputMan::~UInputMan() {
3232
void UInputMan::Clear() {
3333
m_SkipHandlingSpecialInput = false;
3434
m_TextInput.clear();
35-
;
3635
m_NumJoysticks = 0;
3736
m_OverrideInput = false;
38-
m_AbsoluteMousePos.Reset();
39-
m_RawMouseMovement.Reset();
40-
m_AnalogMouseData.Reset();
4137
m_MouseSensitivity = 0.6F;
42-
m_MouseWheelChange = 0;
4338
m_TrapMousePos = false;
4439
m_PlayerScreenMouseBounds = {0, 0, 0, 0};
4540
m_MouseTrapRadius = 350;
@@ -89,9 +84,9 @@ int UInputMan::Initialize() {
8984
g_ConsoleMan.PrintString("ERROR: Failed to connect gamepad " + std::to_string(index) + " " + std::string(SDL_GetError()));
9085
continue;
9186
}
92-
SDL_SetGamepadPlayerIndex(controller, index);
93-
s_PrevJoystickStates[controllerIndex] = Gamepad(index, joysticks[index], SDL_GAMEPAD_AXIS_COUNT, SDL_GAMEPAD_BUTTON_COUNT);
94-
s_ChangedJoystickStates[controllerIndex] = Gamepad(index, joysticks[index], SDL_GAMEPAD_AXIS_COUNT, SDL_GAMEPAD_BUTTON_COUNT);
87+
SDL_SetGamepadPlayerIndex(controller, controllerIndex);
88+
s_PrevJoystickStates[controllerIndex] = Gamepad(controllerIndex, joysticks[index], SDL_GAMEPAD_AXIS_COUNT, SDL_GAMEPAD_BUTTON_COUNT);
89+
s_ChangedJoystickStates[controllerIndex] = Gamepad(controllerIndex, joysticks[index], SDL_GAMEPAD_AXIS_COUNT, SDL_GAMEPAD_BUTTON_COUNT);
9590
auto playerScheme = std::find_if(m_ControlScheme.begin(), m_ControlScheme.end(), [controllerIndex](auto& scheme) { return scheme.GetDevice() == controllerIndex + InputDevice::DEVICE_GAMEPAD_1; });
9691
playerScheme->SetDeviceID({.gamepad = joysticks[index]});
9792
controllerIndex++;
@@ -102,8 +97,8 @@ int UInputMan::Initialize() {
10297
g_ConsoleMan.PrintString("ERROR: Failed to connect joystick.");
10398
continue;
10499
}
105-
s_PrevJoystickStates[controllerIndex] = Gamepad(index, joysticks[index], SDL_GetNumJoystickAxes(joy), SDL_GetNumJoystickButtons(joy));
106-
s_ChangedJoystickStates[controllerIndex] = Gamepad(index, joysticks[index], SDL_GetNumJoystickAxes(joy), SDL_GetNumJoystickButtons(joy));
100+
s_PrevJoystickStates[controllerIndex] = Gamepad(controllerIndex, joysticks[index], SDL_GetNumJoystickAxes(joy), SDL_GetNumJoystickButtons(joy));
101+
s_ChangedJoystickStates[controllerIndex] = Gamepad(controllerIndex, joysticks[index], SDL_GetNumJoystickAxes(joy), SDL_GetNumJoystickButtons(joy));
107102
auto playerScheme = std::find_if(m_ControlScheme.begin(), m_ControlScheme.end(), [controllerIndex](auto& scheme) { return scheme.GetDevice() == controllerIndex + InputDevice::DEVICE_GAMEPAD_1; });
108103
playerScheme->SetDeviceID({.gamepad = joysticks[index]});
109104
controllerIndex++;
@@ -163,7 +158,7 @@ Vector UInputMan::AnalogAimValues(int whichPlayer) {
163158
Vector aimValues(0, 0);
164159
if (device == InputDevice::DEVICE_MOUSE_KEYB) {
165160
if (!m_EnableMultiMouseKeyboard) {
166-
aimValues = (m_AnalogMouseData / m_MouseTrapRadius);
161+
aimValues = (m_MouseStates.at(0).analogAim / m_MouseTrapRadius);
167162
} else {
168163
if (auto mouse = m_MouseStates.find(m_ControlScheme.at(whichPlayer).GetDeviceID().mouseKeyboard.mouse); mouse != m_MouseStates.end()) {
169164
aimValues = mouse->second.analogAim / m_MouseTrapRadius;
@@ -367,7 +362,7 @@ Vector UInputMan::GetAbsoluteMousePosition(int whichPlayer) const {
367362

368363
void UInputMan::SetAbsoluteMousePosition(const Vector& pos, int whichPlayer) {
369364
if (whichPlayer == Players::NoPlayer || !m_EnableMultiMouseKeyboard) {
370-
m_AbsoluteMousePos = pos;
365+
m_MouseStates.at(0).position = pos;
371366
} else if (m_ControlScheme.at(whichPlayer).GetDevice() == InputDevice::DEVICE_MOUSE_KEYB) {
372367
if (auto mouse = m_MouseStates.find(m_ControlScheme.at(whichPlayer).GetDeviceID().mouseKeyboard.mouse); mouse != m_MouseStates.end()) {
373368
mouse->second.position = pos;
@@ -453,6 +448,20 @@ void UInputMan::ClearMouseButtons() {
453448
}
454449
}
455450

451+
int UInputMan::MouseWheelMovedByPlayer(int player) const {
452+
if (player == Players::NoPlayer || player < Players::PlayerOne || player >= Players::MaxPlayerCount || !m_EnableMultiMouseKeyboard) {
453+
return m_MouseStates.at(0).wheelChange;
454+
}
455+
InputDevice playerInput = m_ControlScheme.at(player).GetDevice();
456+
if (playerInput == InputDevice::DEVICE_MOUSE_KEYB) {
457+
DeviceID playerDevice = m_ControlScheme.at(player).GetDeviceID();
458+
if (auto mouse = m_MouseStates.find(playerDevice.mouseKeyboard.mouse); mouse != m_MouseStates.end()) {
459+
return mouse->second.wheelChange;
460+
}
461+
}
462+
return m_MouseStates.at(0).wheelChange;
463+
}
464+
456465
bool UInputMan::AnyMouseButtonPress(SDL_MouseID mouseID) const {
457466
for (int button = MouseButtons::MOUSE_LEFT; button < MouseButtons::MAX_MOUSE_BUTTONS; ++button) {
458467
if (MouseButtonPressed(button, NoPlayer, mouseID)) {
@@ -490,9 +499,9 @@ void UInputMan::ForceMouseWithinBox(int x, int y, int width, int height, int whi
490499
rightMostPos = std::clamp(leftPos + width, leftPos, rightMostPos - 1);
491500
bottomMostPos = std::clamp(topPos + height, topPos, bottomMostPos - 1);
492501

493-
if (!WithinBox(m_AbsoluteMousePos, static_cast<float>(leftPos), static_cast<float>(topPos), static_cast<float>(rightMostPos), static_cast<float>(bottomMostPos))) {
494-
int limitX = std::clamp(m_AbsoluteMousePos.GetFloorIntX(), leftPos, rightMostPos);
495-
int limitY = std::clamp(m_AbsoluteMousePos.GetFloorIntY(), topPos, bottomMostPos);
502+
if (!WithinBox(m_MouseStates[0].position, static_cast<float>(leftPos), static_cast<float>(topPos), static_cast<float>(rightMostPos), static_cast<float>(bottomMostPos))) {
503+
int limitX = std::clamp(m_MouseStates[0].position.GetFloorIntX(), leftPos, rightMostPos);
504+
int limitY = std::clamp(m_MouseStates[0].position.GetFloorIntY(), topPos, bottomMostPos);
496505
SDL_WarpMouseInWindow(g_WindowMan.GetWindow(), limitX, limitY);
497506
}
498507
} else {
@@ -852,8 +861,6 @@ int UInputMan::Update() {
852861
}
853862

854863
m_TextInput.clear();
855-
m_MouseWheelChange = 0;
856-
m_RawMouseMovement.Reset();
857864
for (auto& [mouseID, mouse]: m_MouseStates) {
858865
mouse.wheelChange = 0;
859866
mouse.relativeMotion.Reset();
@@ -931,15 +938,13 @@ int UInputMan::Update() {
931938
m_MouseStates[0].position = {inputEvent.motion.x, inputEvent.motion.y};
932939
m_MouseStates[0].relativeMotion += {inputEvent.motion.xrel, inputEvent.motion.yrel};
933940

934-
m_RawMouseMovement += Vector(static_cast<float>(inputEvent.motion.xrel), static_cast<float>(inputEvent.motion.yrel));
935-
m_AbsoluteMousePos.SetXY(static_cast<float>(inputEvent.motion.x), static_cast<float>(inputEvent.motion.y));
936-
937941
if (g_WindowMan.FullyCoversAllDisplays()) {
938942
int windowPosX = 0;
939943
int windowPosY = 0;
940944
SDL_GetWindowPosition(SDL_GetWindowFromID(inputEvent.motion.windowID), &windowPosX, &windowPosY);
941945
Vector windowCoord(static_cast<float>(g_WindowMan.GetDisplayArrangementAbsOffsetX() + windowPosX), static_cast<float>(g_WindowMan.GetDisplayArrangementAbsOffsetY() + windowPosY));
942-
m_AbsoluteMousePos += windowCoord;
946+
mouse.position += windowCoord;
947+
m_MouseStates[0].position += windowCoord;
943948
}
944949
break;
945950
}
@@ -959,7 +964,6 @@ int UInputMan::Update() {
959964
break;
960965
}
961966
case SDL_EVENT_MOUSE_WHEEL: {
962-
m_MouseWheelChange += inputEvent.wheel.direction == SDL_MOUSEWHEEL_NORMAL ? inputEvent.wheel.y : -inputEvent.wheel.y;
963967
m_MouseStates[inputEvent.wheel.which].wheelChange += inputEvent.wheel.direction == SDL_MOUSEWHEEL_NORMAL ? inputEvent.wheel.y : -inputEvent.wheel.y;
964968
m_MouseStates[0].wheelChange += inputEvent.wheel.direction == SDL_MOUSEWHEEL_NORMAL ? inputEvent.wheel.y : -inputEvent.wheel.y;
965969
break;
@@ -988,9 +992,9 @@ int UInputMan::Update() {
988992
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
989993
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
990994
if (std::vector<Gamepad>::iterator device = std::find(s_PrevJoystickStates.begin(), s_PrevJoystickStates.end(), inputEvent.type == SDL_EVENT_GAMEPAD_AXIS_MOTION ? inputEvent.gaxis.which : inputEvent.jaxis.which); device != s_PrevJoystickStates.end()) {
991-
if (SDL_IsGamepad(device->m_DeviceIndex) && inputEvent.type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {
995+
if (SDL_IsGamepad(device->m_JoystickID) && inputEvent.type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {
992996
UpdateJoystickAxis(device, inputEvent.gaxis.axis, inputEvent.gaxis.value);
993-
} else if (!SDL_IsGamepad(device->m_DeviceIndex)) {
997+
} else if (!SDL_IsGamepad(device->m_JoystickID)) {
994998
UpdateJoystickAxis(device, inputEvent.jaxis.axis, inputEvent.jaxis.value);
995999
}
9961000
}
@@ -1003,7 +1007,7 @@ int UInputMan::Update() {
10031007
if (std::vector<Gamepad>::iterator device = std::find(s_PrevJoystickStates.begin(), s_PrevJoystickStates.end(), joystickEvent ? inputEvent.jbutton.which : inputEvent.gbutton.which); device != s_PrevJoystickStates.end()) {
10041008
int button = -1;
10051009
int down = false;
1006-
if (SDL_IsGamepad(device->m_DeviceIndex)) {
1010+
if (SDL_IsGamepad(device->m_JoystickID)) {
10071011
if (inputEvent.type == SDL_EVENT_GAMEPAD_BUTTON_UP || inputEvent.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
10081012
button = inputEvent.gbutton.button;
10091013
down = inputEvent.gbutton.down;
@@ -1028,7 +1032,7 @@ int UInputMan::Update() {
10281032
case SDL_EVENT_JOYSTICK_REMOVED:
10291033
case SDL_EVENT_GAMEPAD_REMOVED:
10301034
if (std::vector<Gamepad>::iterator prevDevice = std::find(s_PrevJoystickStates.begin(), s_PrevJoystickStates.end(), inputEvent.jdevice.which); prevDevice != s_PrevJoystickStates.end()) {
1031-
g_ConsoleMan.PrintString("INFO: Gamepad " + std::to_string(prevDevice->m_DeviceIndex + 1) + " disconnected!");
1035+
g_ConsoleMan.PrintString("INFO: Gamepad " + std::to_string(prevDevice - s_PrevJoystickStates.begin() + 1) + " disconnected!");
10321036
SDL_CloseGamepad(SDL_GetGamepadFromID(prevDevice->m_JoystickID));
10331037
prevDevice->m_JoystickID = -1;
10341038
std::fill(prevDevice->m_Axis.begin(), prevDevice->m_Axis.end(), 0);
@@ -1046,7 +1050,6 @@ int UInputMan::Update() {
10461050
}
10471051
}
10481052
m_EventQueue.clear();
1049-
m_RawMouseMovement *= m_MouseSensitivity;
10501053
for (auto& [mouseID, mouse]: m_MouseStates) {
10511054
mouse.relativeMotion *= m_MouseSensitivity;
10521055
}
@@ -1170,9 +1173,6 @@ void UInputMan::HandleSpecialInput() {
11701173
void UInputMan::UpdateMouseInput() {
11711174
// Detect and store mouse movement input, translated to analog stick emulation
11721175
// TODO: Figure out a less shit solution to updating the mouse in GUIs when there are no mouse players configured, i.e. no player input scheme is using mouse+keyboard. For not just check if we're out of Activity.
1173-
m_AnalogMouseData.m_X += m_RawMouseMovement.m_X * 3;
1174-
m_AnalogMouseData.m_Y += m_RawMouseMovement.m_Y * 3;
1175-
m_AnalogMouseData.CapMagnitude(m_MouseTrapRadius);
11761176
for (auto& [mouseID, mouse]: m_MouseStates) {
11771177
mouse.analogAim += mouse.relativeMotion * 3;
11781178
mouse.analogAim.CapMagnitude(m_MouseTrapRadius);
@@ -1190,8 +1190,8 @@ void UInputMan::UpdateMouseInput() {
11901190

11911191
// Enable the mouse cursor positioning again after having been disabled. Only do this when the mouse is within the drawing area so it
11921192
// won't cause the whole window to move if the user clicks the title bar and unintentionally drags it due to programmatic positioning.
1193-
int mousePosX = m_AbsoluteMousePos.m_X / g_WindowMan.GetResMultiplier();
1194-
int mousePosY = m_AbsoluteMousePos.m_Y / g_WindowMan.GetResMultiplier();
1193+
int mousePosX = m_MouseStates.at(0).position.m_X / g_WindowMan.GetResMultiplier();
1194+
int mousePosY = m_MouseStates.at(0).position.m_Y / g_WindowMan.GetResMultiplier();
11951195
if (m_DisableMouseMoving && m_PrepareToEnableMouseMoving && (mousePosX >= 0 && mousePosX < g_WindowMan.GetResX() && mousePosY >= 0 && mousePosY < g_WindowMan.GetResY())) {
11961196
m_DisableMouseMoving = m_PrepareToEnableMouseMoving = false;
11971197
}
@@ -1284,25 +1284,25 @@ void UInputMan::UpdateJoystickDigitalAxis() {
12841284
}
12851285
}
12861286

1287-
void UInputMan::HandleGamepadHotPlug(SDL_JoystickID deviceIndex) {
1287+
void UInputMan::HandleGamepadHotPlug(SDL_JoystickID joystickID) {
12881288
SDL_Joystick* controller = nullptr;
12891289
int controllerIndex = 0;
12901290

12911291
for (controllerIndex = 0; controllerIndex < s_PrevJoystickStates.size(); ++controllerIndex) {
1292-
if (s_PrevJoystickStates[controllerIndex].m_JoystickID == deviceIndex) {
1292+
if (s_PrevJoystickStates[controllerIndex].m_JoystickID == joystickID) {
12931293
return;
12941294
}
12951295
if (s_PrevJoystickStates[controllerIndex].m_JoystickID == -1) {
1296-
if (SDL_IsGamepad(deviceIndex)) {
1297-
SDL_Gamepad* gameController = SDL_OpenGamepad(deviceIndex);
1296+
if (SDL_IsGamepad(joystickID)) {
1297+
SDL_Gamepad* gameController = SDL_OpenGamepad(joystickID);
12981298
if (!gameController) {
12991299
g_ConsoleMan.PrintString("ERROR: Failed to connect Gamepad!");
13001300
break;
13011301
}
13021302
controller = SDL_GetGamepadJoystick(gameController);
13031303
SDL_SetGamepadPlayerIndex(gameController, controllerIndex);
13041304
} else {
1305-
controller = SDL_OpenJoystick(deviceIndex);
1305+
controller = SDL_OpenJoystick(joystickID);
13061306
}
13071307
if (!controller) {
13081308
g_ConsoleMan.PrintString("ERROR: Failed to connect Gamepad!");
@@ -1320,15 +1320,15 @@ void UInputMan::HandleGamepadHotPlug(SDL_JoystickID deviceIndex) {
13201320
if (controller) {
13211321
int numAxis = 0;
13221322
int numButtons = 0;
1323-
if (SDL_IsGamepad(deviceIndex)) {
1323+
if (SDL_IsGamepad(joystickID)) {
13241324
numAxis = SDL_GAMEPAD_AXIS_COUNT;
13251325
numButtons = SDL_GAMEPAD_BUTTON_COUNT;
13261326
} else {
13271327
numAxis = SDL_GetNumJoystickAxes(controller);
13281328
numButtons = SDL_GetNumJoystickButtons(controller);
13291329
}
1330-
s_PrevJoystickStates[controllerIndex] = Gamepad(controllerIndex, deviceIndex, numAxis, numButtons);
1331-
s_ChangedJoystickStates[controllerIndex] = Gamepad(controllerIndex, deviceIndex, numAxis, numButtons);
1330+
s_PrevJoystickStates[controllerIndex] = Gamepad(controllerIndex, joystickID, numAxis, numButtons);
1331+
s_ChangedJoystickStates[controllerIndex] = Gamepad(controllerIndex, joystickID, numAxis, numButtons);
13321332
m_NumJoysticks++;
13331333
}
13341334
}

Source/Managers/UInputMan.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -343,15 +343,12 @@ namespace RTE {
343343

344344
/// Gets whether the mouse wheel has been moved past the threshold limit in either direction this frame.
345345
/// @return The direction the mouse wheel has been moved which is past that threshold. 0 means not past, negative means moved down, positive means moved up.
346-
int MouseWheelMoved() const { return m_MouseWheelChange; }
346+
int MouseWheelMoved() const { return m_MouseStates.at(0).wheelChange; }
347347

348348
/// Gets the relative mouse wheel position for the specified player.
349349
/// @param player The player to get mouse wheel position for.
350350
/// @return The relative mouse wheel position for the specified player.
351-
int MouseWheelMovedByPlayer(int player) const {
352-
return m_MouseWheelChange;
353-
}
354-
351+
int MouseWheelMovedByPlayer(int player) const;
355352
/// Return true if there are any mouse button presses at all.
356353
/// @return Whether any mouse buttons have been pressed at all since last frame.
357354
bool AnyMouseButtonPress(SDL_MouseID mouseID = 0) const;
@@ -509,11 +506,7 @@ namespace RTE {
509506
std::array<InputScheme, Players::MaxPlayerCount> m_ControlScheme; //!< Which control scheme is being used by each player.
510507
const Icon* m_DeviceIcons[InputDevice::DEVICE_COUNT]; //!< The Icons representing all different devices.
511508

512-
Vector m_AbsoluteMousePos; //!< The absolute mouse position in screen coordinates.
513-
Vector m_RawMouseMovement; //!< The raw absolute movement of the mouse between the last two Updates.
514-
Vector m_AnalogMouseData; //!< The emulated analog stick position of the mouse.
515509
float m_MouseSensitivity; //!< Mouse sensitivity multiplier while in Activity. HAS NO EFFECT IN MENUS.
516-
int m_MouseWheelChange; //!< The relative mouse wheel position since last reset of it.
517510

518511
bool m_TrapMousePos; //!< Whether the mouse is trapped in the middle of the screen each update or not.
519512
float m_MouseTrapRadius; //!< The radius (in pixels) of the circle trapping the mouse for analog mouse data.
@@ -532,8 +525,8 @@ namespace RTE {
532525
bool m_PrepareToEnableMouseMoving;
533526

534527
static constexpr double c_GamepadAxisLimit = 32767.0; //!< Maximum axis value as defined by SDL (int16 max).
535-
static constexpr int c_AxisDigitalPressedThreshold = 8192; //!< Digital Axis threshold value as defined by allegro.
536-
static constexpr int c_AxisDigitalReleasedThreshold = c_AxisDigitalPressedThreshold - 100; //!< Digital Axis release threshold, to debounce values.
528+
static constexpr int c_AxisDigitalPressedThreshold = 16384; //!< Digital Axis threshold value as defined by allegro.
529+
static constexpr int c_AxisDigitalReleasedThreshold = 8192; //!< Digital Axis release threshold, to debounce values.
537530

538531
#pragma region Mouse Handling
539532
/// Forces the mouse within a specific player's screen area.
@@ -606,8 +599,8 @@ namespace RTE {
606599
void UpdateJoystickDigitalAxis();
607600

608601
/// Connect a joystick or gamepad device and add it to the joystick list if a slot is available (up to max player count).
609-
/// @param deviceIndex The device index (generated by the connected event or a value up to SDL_NumJoysticks()).
610-
void HandleGamepadHotPlug(SDL_JoystickID deviceIndex);
602+
/// @param joystickID The SDL_JoystickID of the added Gamepad, usually from the corresponding device event.
603+
void HandleGamepadHotPlug(SDL_JoystickID joystickID);
611604
#pragma endregion
612605

613606
/// Clears all the member variables of this UInputMan, effectively resetting the members of this abstraction level only.

Source/System/Gamepad.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace RTE {
77

88
/// Structure for storing SDL_Gamepad or SDL_Joystick states.
99
struct Gamepad {
10-
int m_DeviceIndex = -1; //!< The SDL device index.
10+
int m_DeviceIndex = -1; //!< The internal device index.
1111
SDL_JoystickID m_JoystickID = -1; //!< The joystick ID for event handling.
1212
std::vector<int> m_Axis; //!< Array of analog axis states.
1313
std::vector<int> m_DigitalAxis; //!< Array of digital axis states. Should be updated when analog axis crosses half value 8192.

0 commit comments

Comments
 (0)