diff --git a/.gitignore b/.gitignore index 7122989a4..efb3ceae1 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ compile_commands.json **/.ccls-cache **/.cache +**/.clangd + **/build* diff --git a/Source/Managers/UInputMan.cpp b/Source/Managers/UInputMan.cpp index 3b5af044f..04fcc80b6 100644 --- a/Source/Managers/UInputMan.cpp +++ b/Source/Managers/UInputMan.cpp @@ -32,14 +32,9 @@ UInputMan::~UInputMan() { void UInputMan::Clear() { m_SkipHandlingSpecialInput = false; m_TextInput.clear(); - ; m_NumJoysticks = 0; m_OverrideInput = false; - m_AbsoluteMousePos.Reset(); - m_RawMouseMovement.Reset(); - m_AnalogMouseData.Reset(); m_MouseSensitivity = 0.6F; - m_MouseWheelChange = 0; m_TrapMousePos = false; m_PlayerScreenMouseBounds = {0, 0, 0, 0}; m_MouseTrapRadius = 350; @@ -89,9 +84,9 @@ int UInputMan::Initialize() { g_ConsoleMan.PrintString("ERROR: Failed to connect gamepad " + std::to_string(index) + " " + std::string(SDL_GetError())); continue; } - SDL_SetGamepadPlayerIndex(controller, index); - s_PrevJoystickStates[controllerIndex] = Gamepad(index, joysticks[index], SDL_GAMEPAD_AXIS_COUNT, SDL_GAMEPAD_BUTTON_COUNT); - s_ChangedJoystickStates[controllerIndex] = Gamepad(index, joysticks[index], SDL_GAMEPAD_AXIS_COUNT, SDL_GAMEPAD_BUTTON_COUNT); + SDL_SetGamepadPlayerIndex(controller, controllerIndex); + s_PrevJoystickStates[controllerIndex] = Gamepad(controllerIndex, joysticks[index], SDL_GAMEPAD_AXIS_COUNT, SDL_GAMEPAD_BUTTON_COUNT); + s_ChangedJoystickStates[controllerIndex] = Gamepad(controllerIndex, joysticks[index], SDL_GAMEPAD_AXIS_COUNT, SDL_GAMEPAD_BUTTON_COUNT); auto playerScheme = std::find_if(m_ControlScheme.begin(), m_ControlScheme.end(), [controllerIndex](auto& scheme) { return scheme.GetDevice() == controllerIndex + InputDevice::DEVICE_GAMEPAD_1; }); playerScheme->SetDeviceID({.gamepad = joysticks[index]}); controllerIndex++; @@ -102,8 +97,8 @@ int UInputMan::Initialize() { g_ConsoleMan.PrintString("ERROR: Failed to connect joystick."); continue; } - s_PrevJoystickStates[controllerIndex] = Gamepad(index, joysticks[index], SDL_GetNumJoystickAxes(joy), SDL_GetNumJoystickButtons(joy)); - s_ChangedJoystickStates[controllerIndex] = Gamepad(index, joysticks[index], SDL_GetNumJoystickAxes(joy), SDL_GetNumJoystickButtons(joy)); + s_PrevJoystickStates[controllerIndex] = Gamepad(controllerIndex, joysticks[index], SDL_GetNumJoystickAxes(joy), SDL_GetNumJoystickButtons(joy)); + s_ChangedJoystickStates[controllerIndex] = Gamepad(controllerIndex, joysticks[index], SDL_GetNumJoystickAxes(joy), SDL_GetNumJoystickButtons(joy)); auto playerScheme = std::find_if(m_ControlScheme.begin(), m_ControlScheme.end(), [controllerIndex](auto& scheme) { return scheme.GetDevice() == controllerIndex + InputDevice::DEVICE_GAMEPAD_1; }); playerScheme->SetDeviceID({.gamepad = joysticks[index]}); controllerIndex++; @@ -163,7 +158,7 @@ Vector UInputMan::AnalogAimValues(int whichPlayer) { Vector aimValues(0, 0); if (device == InputDevice::DEVICE_MOUSE_KEYB) { if (!m_EnableMultiMouseKeyboard) { - aimValues = (m_AnalogMouseData / m_MouseTrapRadius); + aimValues = (m_MouseStates.at(0).analogAim / m_MouseTrapRadius); } else { if (auto mouse = m_MouseStates.find(m_ControlScheme.at(whichPlayer).GetDeviceID().mouseKeyboard.mouse); mouse != m_MouseStates.end()) { aimValues = mouse->second.analogAim / m_MouseTrapRadius; @@ -367,7 +362,7 @@ Vector UInputMan::GetAbsoluteMousePosition(int whichPlayer) const { void UInputMan::SetAbsoluteMousePosition(const Vector& pos, int whichPlayer) { if (whichPlayer == Players::NoPlayer || !m_EnableMultiMouseKeyboard) { - m_AbsoluteMousePos = pos; + m_MouseStates.at(0).position = pos; } else if (m_ControlScheme.at(whichPlayer).GetDevice() == InputDevice::DEVICE_MOUSE_KEYB) { if (auto mouse = m_MouseStates.find(m_ControlScheme.at(whichPlayer).GetDeviceID().mouseKeyboard.mouse); mouse != m_MouseStates.end()) { mouse->second.position = pos; @@ -453,6 +448,20 @@ void UInputMan::ClearMouseButtons() { } } +int UInputMan::MouseWheelMovedByPlayer(int player) const { + if (player == Players::NoPlayer || player < Players::PlayerOne || player >= Players::MaxPlayerCount || !m_EnableMultiMouseKeyboard) { + return m_MouseStates.at(0).wheelChange; + } + InputDevice playerInput = m_ControlScheme.at(player).GetDevice(); + if (playerInput == InputDevice::DEVICE_MOUSE_KEYB) { + DeviceID playerDevice = m_ControlScheme.at(player).GetDeviceID(); + if (auto mouse = m_MouseStates.find(playerDevice.mouseKeyboard.mouse); mouse != m_MouseStates.end()) { + return mouse->second.wheelChange; + } + } + return m_MouseStates.at(0).wheelChange; +} + bool UInputMan::AnyMouseButtonPress(SDL_MouseID mouseID) const { for (int button = MouseButtons::MOUSE_LEFT; button < MouseButtons::MAX_MOUSE_BUTTONS; ++button) { if (MouseButtonPressed(button, NoPlayer, mouseID)) { @@ -490,9 +499,9 @@ void UInputMan::ForceMouseWithinBox(int x, int y, int width, int height, int whi rightMostPos = std::clamp(leftPos + width, leftPos, rightMostPos - 1); bottomMostPos = std::clamp(topPos + height, topPos, bottomMostPos - 1); - if (!WithinBox(m_AbsoluteMousePos, static_cast(leftPos), static_cast(topPos), static_cast(rightMostPos), static_cast(bottomMostPos))) { - int limitX = std::clamp(m_AbsoluteMousePos.GetFloorIntX(), leftPos, rightMostPos); - int limitY = std::clamp(m_AbsoluteMousePos.GetFloorIntY(), topPos, bottomMostPos); + if (!WithinBox(m_MouseStates[0].position, static_cast(leftPos), static_cast(topPos), static_cast(rightMostPos), static_cast(bottomMostPos))) { + int limitX = std::clamp(m_MouseStates[0].position.GetFloorIntX(), leftPos, rightMostPos); + int limitY = std::clamp(m_MouseStates[0].position.GetFloorIntY(), topPos, bottomMostPos); SDL_WarpMouseInWindow(g_WindowMan.GetWindow(), limitX, limitY); } } else { @@ -852,8 +861,6 @@ int UInputMan::Update() { } m_TextInput.clear(); - m_MouseWheelChange = 0; - m_RawMouseMovement.Reset(); for (auto& [mouseID, mouse]: m_MouseStates) { mouse.wheelChange = 0; mouse.relativeMotion.Reset(); @@ -931,15 +938,13 @@ int UInputMan::Update() { m_MouseStates[0].position = {inputEvent.motion.x, inputEvent.motion.y}; m_MouseStates[0].relativeMotion += {inputEvent.motion.xrel, inputEvent.motion.yrel}; - m_RawMouseMovement += Vector(static_cast(inputEvent.motion.xrel), static_cast(inputEvent.motion.yrel)); - m_AbsoluteMousePos.SetXY(static_cast(inputEvent.motion.x), static_cast(inputEvent.motion.y)); - if (g_WindowMan.FullyCoversAllDisplays()) { int windowPosX = 0; int windowPosY = 0; SDL_GetWindowPosition(SDL_GetWindowFromID(inputEvent.motion.windowID), &windowPosX, &windowPosY); Vector windowCoord(static_cast(g_WindowMan.GetDisplayArrangementAbsOffsetX() + windowPosX), static_cast(g_WindowMan.GetDisplayArrangementAbsOffsetY() + windowPosY)); - m_AbsoluteMousePos += windowCoord; + mouse.position += windowCoord; + m_MouseStates[0].position += windowCoord; } break; } @@ -959,7 +964,6 @@ int UInputMan::Update() { break; } case SDL_EVENT_MOUSE_WHEEL: { - m_MouseWheelChange += inputEvent.wheel.direction == SDL_MOUSEWHEEL_NORMAL ? inputEvent.wheel.y : -inputEvent.wheel.y; m_MouseStates[inputEvent.wheel.which].wheelChange += inputEvent.wheel.direction == SDL_MOUSEWHEEL_NORMAL ? inputEvent.wheel.y : -inputEvent.wheel.y; m_MouseStates[0].wheelChange += inputEvent.wheel.direction == SDL_MOUSEWHEEL_NORMAL ? inputEvent.wheel.y : -inputEvent.wheel.y; break; @@ -988,9 +992,9 @@ int UInputMan::Update() { case SDL_EVENT_GAMEPAD_AXIS_MOTION: case SDL_EVENT_JOYSTICK_AXIS_MOTION: if (std::vector::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()) { - if (SDL_IsGamepad(device->m_DeviceIndex) && inputEvent.type == SDL_EVENT_GAMEPAD_AXIS_MOTION) { + if (SDL_IsGamepad(device->m_JoystickID) && inputEvent.type == SDL_EVENT_GAMEPAD_AXIS_MOTION) { UpdateJoystickAxis(device, inputEvent.gaxis.axis, inputEvent.gaxis.value); - } else if (!SDL_IsGamepad(device->m_DeviceIndex)) { + } else if (!SDL_IsGamepad(device->m_JoystickID)) { UpdateJoystickAxis(device, inputEvent.jaxis.axis, inputEvent.jaxis.value); } } @@ -1003,7 +1007,7 @@ int UInputMan::Update() { if (std::vector::iterator device = std::find(s_PrevJoystickStates.begin(), s_PrevJoystickStates.end(), joystickEvent ? inputEvent.jbutton.which : inputEvent.gbutton.which); device != s_PrevJoystickStates.end()) { int button = -1; int down = false; - if (SDL_IsGamepad(device->m_DeviceIndex)) { + if (SDL_IsGamepad(device->m_JoystickID)) { if (inputEvent.type == SDL_EVENT_GAMEPAD_BUTTON_UP || inputEvent.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) { button = inputEvent.gbutton.button; down = inputEvent.gbutton.down; @@ -1028,7 +1032,7 @@ int UInputMan::Update() { case SDL_EVENT_JOYSTICK_REMOVED: case SDL_EVENT_GAMEPAD_REMOVED: if (std::vector::iterator prevDevice = std::find(s_PrevJoystickStates.begin(), s_PrevJoystickStates.end(), inputEvent.jdevice.which); prevDevice != s_PrevJoystickStates.end()) { - g_ConsoleMan.PrintString("INFO: Gamepad " + std::to_string(prevDevice->m_DeviceIndex + 1) + " disconnected!"); + g_ConsoleMan.PrintString("INFO: Gamepad " + std::to_string(prevDevice - s_PrevJoystickStates.begin() + 1) + " disconnected!"); SDL_CloseGamepad(SDL_GetGamepadFromID(prevDevice->m_JoystickID)); prevDevice->m_JoystickID = -1; std::fill(prevDevice->m_Axis.begin(), prevDevice->m_Axis.end(), 0); @@ -1046,7 +1050,6 @@ int UInputMan::Update() { } } m_EventQueue.clear(); - m_RawMouseMovement *= m_MouseSensitivity; for (auto& [mouseID, mouse]: m_MouseStates) { mouse.relativeMotion *= m_MouseSensitivity; } @@ -1170,9 +1173,6 @@ void UInputMan::HandleSpecialInput() { void UInputMan::UpdateMouseInput() { // Detect and store mouse movement input, translated to analog stick emulation // 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. - m_AnalogMouseData.m_X += m_RawMouseMovement.m_X * 3; - m_AnalogMouseData.m_Y += m_RawMouseMovement.m_Y * 3; - m_AnalogMouseData.CapMagnitude(m_MouseTrapRadius); for (auto& [mouseID, mouse]: m_MouseStates) { mouse.analogAim += mouse.relativeMotion * 3; mouse.analogAim.CapMagnitude(m_MouseTrapRadius); @@ -1190,8 +1190,8 @@ void UInputMan::UpdateMouseInput() { // Enable the mouse cursor positioning again after having been disabled. Only do this when the mouse is within the drawing area so it // won't cause the whole window to move if the user clicks the title bar and unintentionally drags it due to programmatic positioning. - int mousePosX = m_AbsoluteMousePos.m_X / g_WindowMan.GetResMultiplier(); - int mousePosY = m_AbsoluteMousePos.m_Y / g_WindowMan.GetResMultiplier(); + int mousePosX = m_MouseStates.at(0).position.m_X / g_WindowMan.GetResMultiplier(); + int mousePosY = m_MouseStates.at(0).position.m_Y / g_WindowMan.GetResMultiplier(); if (m_DisableMouseMoving && m_PrepareToEnableMouseMoving && (mousePosX >= 0 && mousePosX < g_WindowMan.GetResX() && mousePosY >= 0 && mousePosY < g_WindowMan.GetResY())) { m_DisableMouseMoving = m_PrepareToEnableMouseMoving = false; } @@ -1284,17 +1284,17 @@ void UInputMan::UpdateJoystickDigitalAxis() { } } -void UInputMan::HandleGamepadHotPlug(SDL_JoystickID deviceIndex) { +void UInputMan::HandleGamepadHotPlug(SDL_JoystickID joystickID) { SDL_Joystick* controller = nullptr; int controllerIndex = 0; for (controllerIndex = 0; controllerIndex < s_PrevJoystickStates.size(); ++controllerIndex) { - if (s_PrevJoystickStates[controllerIndex].m_JoystickID == deviceIndex) { + if (s_PrevJoystickStates[controllerIndex].m_JoystickID == joystickID) { return; } if (s_PrevJoystickStates[controllerIndex].m_JoystickID == -1) { - if (SDL_IsGamepad(deviceIndex)) { - SDL_Gamepad* gameController = SDL_OpenGamepad(deviceIndex); + if (SDL_IsGamepad(joystickID)) { + SDL_Gamepad* gameController = SDL_OpenGamepad(joystickID); if (!gameController) { g_ConsoleMan.PrintString("ERROR: Failed to connect Gamepad!"); break; @@ -1302,7 +1302,7 @@ void UInputMan::HandleGamepadHotPlug(SDL_JoystickID deviceIndex) { controller = SDL_GetGamepadJoystick(gameController); SDL_SetGamepadPlayerIndex(gameController, controllerIndex); } else { - controller = SDL_OpenJoystick(deviceIndex); + controller = SDL_OpenJoystick(joystickID); } if (!controller) { g_ConsoleMan.PrintString("ERROR: Failed to connect Gamepad!"); @@ -1320,15 +1320,15 @@ void UInputMan::HandleGamepadHotPlug(SDL_JoystickID deviceIndex) { if (controller) { int numAxis = 0; int numButtons = 0; - if (SDL_IsGamepad(deviceIndex)) { + if (SDL_IsGamepad(joystickID)) { numAxis = SDL_GAMEPAD_AXIS_COUNT; numButtons = SDL_GAMEPAD_BUTTON_COUNT; } else { numAxis = SDL_GetNumJoystickAxes(controller); numButtons = SDL_GetNumJoystickButtons(controller); } - s_PrevJoystickStates[controllerIndex] = Gamepad(controllerIndex, deviceIndex, numAxis, numButtons); - s_ChangedJoystickStates[controllerIndex] = Gamepad(controllerIndex, deviceIndex, numAxis, numButtons); + s_PrevJoystickStates[controllerIndex] = Gamepad(controllerIndex, joystickID, numAxis, numButtons); + s_ChangedJoystickStates[controllerIndex] = Gamepad(controllerIndex, joystickID, numAxis, numButtons); m_NumJoysticks++; } } diff --git a/Source/Managers/UInputMan.h b/Source/Managers/UInputMan.h index 39003d92c..c0513fe16 100644 --- a/Source/Managers/UInputMan.h +++ b/Source/Managers/UInputMan.h @@ -343,15 +343,12 @@ namespace RTE { /// Gets whether the mouse wheel has been moved past the threshold limit in either direction this frame. /// @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. - int MouseWheelMoved() const { return m_MouseWheelChange; } + int MouseWheelMoved() const { return m_MouseStates.at(0).wheelChange; } /// Gets the relative mouse wheel position for the specified player. /// @param player The player to get mouse wheel position for. /// @return The relative mouse wheel position for the specified player. - int MouseWheelMovedByPlayer(int player) const { - return m_MouseWheelChange; - } - + int MouseWheelMovedByPlayer(int player) const; /// Return true if there are any mouse button presses at all. /// @return Whether any mouse buttons have been pressed at all since last frame. bool AnyMouseButtonPress(SDL_MouseID mouseID = 0) const; @@ -509,11 +506,7 @@ namespace RTE { std::array m_ControlScheme; //!< Which control scheme is being used by each player. const Icon* m_DeviceIcons[InputDevice::DEVICE_COUNT]; //!< The Icons representing all different devices. - Vector m_AbsoluteMousePos; //!< The absolute mouse position in screen coordinates. - Vector m_RawMouseMovement; //!< The raw absolute movement of the mouse between the last two Updates. - Vector m_AnalogMouseData; //!< The emulated analog stick position of the mouse. float m_MouseSensitivity; //!< Mouse sensitivity multiplier while in Activity. HAS NO EFFECT IN MENUS. - int m_MouseWheelChange; //!< The relative mouse wheel position since last reset of it. bool m_TrapMousePos; //!< Whether the mouse is trapped in the middle of the screen each update or not. float m_MouseTrapRadius; //!< The radius (in pixels) of the circle trapping the mouse for analog mouse data. @@ -532,8 +525,8 @@ namespace RTE { bool m_PrepareToEnableMouseMoving; static constexpr double c_GamepadAxisLimit = 32767.0; //!< Maximum axis value as defined by SDL (int16 max). - static constexpr int c_AxisDigitalPressedThreshold = 8192; //!< Digital Axis threshold value as defined by allegro. - static constexpr int c_AxisDigitalReleasedThreshold = c_AxisDigitalPressedThreshold - 100; //!< Digital Axis release threshold, to debounce values. + static constexpr int c_AxisDigitalPressedThreshold = 16384; //!< Digital Axis threshold value as defined by allegro. + static constexpr int c_AxisDigitalReleasedThreshold = 8192; //!< Digital Axis release threshold, to debounce values. #pragma region Mouse Handling /// Forces the mouse within a specific player's screen area. @@ -606,8 +599,8 @@ namespace RTE { void UpdateJoystickDigitalAxis(); /// Connect a joystick or gamepad device and add it to the joystick list if a slot is available (up to max player count). - /// @param deviceIndex The device index (generated by the connected event or a value up to SDL_NumJoysticks()). - void HandleGamepadHotPlug(SDL_JoystickID deviceIndex); + /// @param joystickID The SDL_JoystickID of the added Gamepad, usually from the corresponding device event. + void HandleGamepadHotPlug(SDL_JoystickID joystickID); #pragma endregion /// Clears all the member variables of this UInputMan, effectively resetting the members of this abstraction level only. diff --git a/Source/System/Gamepad.h b/Source/System/Gamepad.h index 6db4ae797..9ca9330b7 100644 --- a/Source/System/Gamepad.h +++ b/Source/System/Gamepad.h @@ -7,7 +7,7 @@ namespace RTE { /// Structure for storing SDL_Gamepad or SDL_Joystick states. struct Gamepad { - int m_DeviceIndex = -1; //!< The SDL device index. + int m_DeviceIndex = -1; //!< The internal device index. SDL_JoystickID m_JoystickID = -1; //!< The joystick ID for event handling. std::vector m_Axis; //!< Array of analog axis states. std::vector m_DigitalAxis; //!< Array of digital axis states. Should be updated when analog axis crosses half value 8192.