From d09172d74d9fc917c527501f2966667a4ea404bb Mon Sep 17 00:00:00 2001 From: Kenix3 Date: Tue, 16 Aug 2022 21:53:45 -0400 Subject: [PATCH] LUS Cleanup: Fixes SDL axis handling. (#1220) * Fixes SDL axis handling. * Removes sensitivities from LUS Should be a game specific feature. * Updates Wii U Controllers to remove sensitivity Also loads legacy controller profiles. * Fixes memory leak in gfx_dxgi_get_key_name Also fixes issue where wchars would be returned in dxgi when getting a key name. --- libultraship/libultraship/ControlDeck.cpp | 90 +++++++++++-------- libultraship/libultraship/ControlDeck.h | 9 +- libultraship/libultraship/Controller.cpp | 4 +- libultraship/libultraship/Controller.h | 19 ++-- libultraship/libultraship/InputEditor.cpp | 15 +--- .../libultraship/Lib/Fast3D/gfx_dxgi.cpp | 6 +- libultraship/libultraship/SDLController.cpp | 63 +++++-------- libultraship/libultraship/WiiUController.cpp | 10 +-- libultraship/libultraship/WiiUGamepad.cpp | 11 +-- 9 files changed, 104 insertions(+), 123 deletions(-) diff --git a/libultraship/libultraship/ControlDeck.cpp b/libultraship/libultraship/ControlDeck.cpp index 0ab8e1371..6e3328053 100644 --- a/libultraship/libultraship/ControlDeck.cpp +++ b/libultraship/libultraship/ControlDeck.cpp @@ -27,7 +27,7 @@ namespace Ship { physicalDevices.clear(); #ifndef __WIIU__ - for (int i = 0; i < SDL_NumJoysticks(); i++) { + for (int32_t i = 0; i < SDL_NumJoysticks(); i++) { if (SDL_IsGameController(i)) { auto sdl = std::make_shared(i); sdl->Open(); @@ -44,7 +44,7 @@ namespace Ship { gamepad->Open(); physicalDevices.push_back(gamepad); - for (int i = 0; i < 4; i++) { + for (int32_t i = 0; i < 4; i++) { auto controller = std::make_shared((WPADChan) i); controller->Open(); physicalDevices.push_back(controller); @@ -53,20 +53,20 @@ namespace Ship { physicalDevices.push_back(std::make_shared("Disconnected", "None", false)); - for (const auto& device : physicalDevices) { - for (int i = 0; i < MAXCONTROLLERS; i++) { + for (const auto device : physicalDevices) { + for (int32_t i = 0; i < MAXCONTROLLERS; i++) { device->CreateDefaultBinding(i); } } - for (int i = 0; i < MAXCONTROLLERS; i++) { + for (int32_t i = 0; i < MAXCONTROLLERS; i++) { virtualDevices.push_back(i == 0 ? 0 : static_cast(physicalDevices.size()) - 1); } LoadControllerSettings(); } - void ControlDeck::SetPhysicalDevice(int slot, int deviceSlot) { + void ControlDeck::SetPhysicalDevice(int32_t slot, int32_t deviceSlot) { const std::shared_ptr backend = physicalDevices[deviceSlot]; virtualDevices[slot] = deviceSlot; *controllerBits |= (backend->Connected()) << slot; @@ -104,7 +104,7 @@ namespace Ship { std::shared_ptr Config = GlobalCtx2::GetInstance()->GetConfig(); for (auto const& val : Config->rjson["Controllers"]["Deck"].items()) { - int slot = std::stoi(val.key().substr(5)); + int32_t slot = std::stoi(val.key().substr(5)); for (size_t dev = 0; dev < physicalDevices.size(); dev++) { std::string guid = physicalDevices[dev]->GetGuid(); @@ -119,7 +119,7 @@ namespace Ship { Config->setString(StringHelper::Sprintf("Controllers.Deck.Slot_%d", (int)i), backend->GetGuid()); } - for (const auto& device : physicalDevices) { + for (const auto device : physicalDevices) { std::string guid = device->GetGuid(); @@ -128,35 +128,59 @@ namespace Ship { if (!(Config->rjson["Controllers"].contains(guid) && Config->rjson["Controllers"][guid].contains(StringHelper::Sprintf("Slot_%d", virtualSlot)))) continue; auto profile = device->getProfile(virtualSlot); - auto rawProfile = Config->rjson["Controllers"][guid][StringHelper::Sprintf("Slot_%d", virtualSlot)]; + auto rawProfile = Config->rjson["Controllers"][guid][StringHelper::Sprintf("Slot_%d", virtualSlot)]; profile->Mappings.clear(); profile->AxisDeadzones.clear(); - profile->AxisSensitivities.clear(); + profile->AxisDeadzones.clear(); profile->GyroData.clear(); - profile->Version = Config->getInt(NESTED("Version", "")); - profile->UseRumble = Config->getBool(NESTED("Rumble.Enabled", "")); - profile->RumbleStrength = Config->getFloat(NESTED("Rumble.Strength", "")); - profile->UseGyro = Config->getBool(NESTED("Gyro.Enabled", "")); - for (auto const& val : rawProfile["AxisDeadzones"].items()) { - profile->AxisDeadzones[std::stoi(val.key())] = val.value(); - } + profile->Version = Config->getInt(NESTED("Version", ""), DEVICE_PROFILE_VERSION_V0); - for (auto const& val : rawProfile["AxisSensitivities"].items()) { - profile->AxisSensitivities[std::stoi(val.key())] = val.value(); - } + switch (profile->Version) { - for (auto const& val : rawProfile["AxisMinimumPress"].items()) { - profile->AxisMinimumPress[std::stoi(val.key())] = val.value(); - } + case DEVICE_PROFILE_VERSION_V0: - for (auto const& val : rawProfile["GyroData"].items()) { - profile->GyroData[std::stoi(val.key())] = val.value(); - } + // Load up defaults for the things we can't load. + device->CreateDefaultBinding(virtualSlot); - for (auto const& val : rawProfile["Mappings"].items()) { - device->SetButtonMapping(virtualSlot, std::stoi(val.key().substr(4)), val.value()); + profile->UseRumble = Config->getBool(NESTED("Rumble.Enabled", "")); + profile->RumbleStrength = Config->getFloat(NESTED("Rumble.Strength", "")); + profile->UseGyro = Config->getBool(NESTED("Gyro.Enabled", "")); + + for (auto const& val : rawProfile["Mappings"].items()) { + device->SetButtonMapping(virtualSlot, std::stoi(val.key().substr(4)), val.value()); + } + + break; + + case DEVICE_PROFILE_VERSION_V1: + profile->UseRumble = Config->getBool(NESTED("Rumble.Enabled", "")); + profile->RumbleStrength = Config->getFloat(NESTED("Rumble.Strength", "")); + profile->UseGyro = Config->getBool(NESTED("Gyro.Enabled", "")); + + for (auto const& val : rawProfile["AxisDeadzones"].items()) { + profile->AxisDeadzones[std::stoi(val.key())] = val.value(); + } + + for (auto const& val : rawProfile["AxisMinimumPress"].items()) { + profile->AxisMinimumPress[std::stoi(val.key())] = val.value(); + } + + for (auto const& val : rawProfile["GyroData"].items()) { + profile->GyroData[std::stoi(val.key())] = val.value(); + } + + for (auto const& val : rawProfile["Mappings"].items()) { + device->SetButtonMapping(virtualSlot, std::stoi(val.key().substr(4)), val.value()); + } + + break; + + // Version is invalid. + default: + device->CreateDefaultBinding(virtualSlot); + break; } } } @@ -194,10 +218,6 @@ namespace Ship { Config->setFloat(NESTED("AxisDeadzones.%d", key), val); } - for (auto const& [key, val] : profile->AxisSensitivities) { - Config->setFloat(NESTED("AxisSensitivities.%d", key), val); - } - for (auto const& [key, val] : profile->AxisMinimumPress) { Config->setFloat(NESTED("AxisMinimumPress.%d", key), val); } @@ -217,7 +237,7 @@ namespace Ship { Config->save(); } - std::shared_ptr ControlDeck::GetPhysicalDevice(int deviceSlot) { + std::shared_ptr ControlDeck::GetPhysicalDevice(int32_t deviceSlot) { return physicalDevices[deviceSlot]; } @@ -225,7 +245,7 @@ namespace Ship { return physicalDevices.size(); } - int ControlDeck::GetVirtualDevice(int slot) { + int32_t ControlDeck::GetVirtualDevice(int32_t slot) { return virtualDevices[slot]; } @@ -233,7 +253,7 @@ namespace Ship { return virtualDevices.size(); } - std::shared_ptr ControlDeck::GetPhysicalDeviceFromVirtualSlot(int slot) { + std::shared_ptr ControlDeck::GetPhysicalDeviceFromVirtualSlot(int32_t slot) { return GetPhysicalDevice(GetVirtualDevice(slot)); } diff --git a/libultraship/libultraship/ControlDeck.h b/libultraship/libultraship/ControlDeck.h index 025bfcde4..d925020c4 100644 --- a/libultraship/libultraship/ControlDeck.h +++ b/libultraship/libultraship/ControlDeck.h @@ -2,6 +2,7 @@ #include "Controller.h" #include +#include "Lib/Mercury/Mercury.h" namespace Ship { @@ -12,11 +13,11 @@ namespace Ship { void WriteToPad(OSContPad* pad) const; void LoadControllerSettings(); void SaveControllerSettings(); - void SetPhysicalDevice(int slot, int deviceSlot); - std::shared_ptr GetPhysicalDevice(int deviceSlot); - std::shared_ptr GetPhysicalDeviceFromVirtualSlot(int slot); + void SetPhysicalDevice(int32_t slot, int32_t deviceSlot); + std::shared_ptr GetPhysicalDevice(int32_t deviceSlot); + std::shared_ptr GetPhysicalDeviceFromVirtualSlot(int32_t slot); size_t GetNumPhysicalDevices(); - int GetVirtualDevice(int slot); + int32_t GetVirtualDevice(int32_t slot); size_t GetNumVirtualDevices(); uint8_t* GetControllerBits(); private: diff --git a/libultraship/libultraship/Controller.cpp b/libultraship/libultraship/Controller.cpp index cb5df333f..c1d32c2a9 100644 --- a/libultraship/libultraship/Controller.cpp +++ b/libultraship/libultraship/Controller.cpp @@ -13,7 +13,7 @@ namespace Ship { Attachment = nullptr; for(int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { - profiles[virtualSlot] = std::make_shared(); + profiles[virtualSlot] = std::make_shared(); ButtonData[virtualSlot] = std::make_shared(); } } @@ -109,7 +109,7 @@ namespace Ship { return ButtonData[virtualSlot]->gyroY; } - std::shared_ptr Controller::getProfile(int32_t virtualSlot) { + std::shared_ptr Controller::getProfile(int32_t virtualSlot) { return profiles[virtualSlot]; } } diff --git a/libultraship/libultraship/Controller.h b/libultraship/libultraship/Controller.h index 0282b6626..76d1c46af 100644 --- a/libultraship/libultraship/Controller.h +++ b/libultraship/libultraship/Controller.h @@ -12,23 +12,26 @@ #define AXIS_SCANCODE_BIT (1 << 9) namespace Ship { - - - - enum GyroDataV0 { + enum GyroData { DRIFT_X, DRIFT_Y, GYRO_SENSITIVITY }; - struct DeviceProfileV0 { + enum DeviceProfileVersion { + DEVICE_PROFILE_VERSION_V0 = 0, + DEVICE_PROFILE_VERSION_V1 = 1 + }; + + #define DEVICE_PROFILE_CURRENT_VERSION DEVICE_PROFILE_VERSION_V1 + + struct DeviceProfile { int32_t Version = 0; bool UseRumble = false; bool UseGyro = false; float RumbleStrength = 1.0f; std::unordered_map AxisDeadzones; std::unordered_map AxisMinimumPress; - std::unordered_map AxisSensitivities; std::unordered_map GyroData; std::map Mappings; }; @@ -55,7 +58,7 @@ namespace Ship { int32_t& getPressedButtons(int32_t virtualSlot); float& getGyroX(int32_t virtualSlot); float& getGyroY(int32_t virtualSlot); - std::shared_ptr getProfile(int32_t virtualSlot); + std::shared_ptr getProfile(int32_t virtualSlot); bool IsRumbling() { return isRumbling; } std::string GetGuid() { return GUID; } virtual const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) = 0; @@ -79,7 +82,7 @@ namespace Ship { float gyroY = 0.0f; }; - std::unordered_map> profiles; + std::unordered_map> profiles; std::unordered_map> ButtonData = {}; }; } diff --git a/libultraship/libultraship/InputEditor.cpp b/libultraship/libultraship/InputEditor.cpp index e97aeee4d..b59a6045d 100644 --- a/libultraship/libultraship/InputEditor.cpp +++ b/libultraship/libultraship/InputEditor.cpp @@ -189,7 +189,7 @@ namespace Ship { ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 8); // 2 is the SDL value for right stick X axis // 3 is the SDL value for right stick Y axis. - DrawVirtualStick("##CameraVirtualStick", ImVec2(Backend->getRightStickX(CurrentPort) / profile->AxisSensitivities[2], Backend->getRightStickY(CurrentPort) / profile->AxisSensitivities[2])); + DrawVirtualStick("##CameraVirtualStick", ImVec2(Backend->getRightStickX(CurrentPort), Backend->getRightStickY(CurrentPort))); ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); @@ -211,19 +211,6 @@ namespace Ship { ImGui::InputFloat("##MDZone", &profile->AxisDeadzones[2], 1.0f, 0.0f, "%.0f"); profile->AxisDeadzones[3] = profile->AxisDeadzones[2]; ImGui::PopItemWidth(); - ImGui::Text("Sensitivity"); - #ifdef __WIIU__ - ImGui::PushItemWidth(80 * 2); - #else - ImGui::PushItemWidth(80); - #endif - // The window has sensitivity per stick, so we need to - // set the sensitivity for both right stick axes here - // SDL_CONTROLLER_AXIS_RIGHTX: 2 - // SDL_CONTROLLER_AXIS_RIGHTY: 3 - ImGui::InputFloat("##MSensitivity", &profile->AxisSensitivities[2], 1.0f, 0.0f, "%.0f"); - profile->AxisSensitivities[3] = profile->AxisSensitivities[2]; - ImGui::PopItemWidth(); ImGui::EndChild(); #ifdef __SWITCH__ SohImGui::EndGroupPanel(43.0f); diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp index 3e81f56fa..b0ea8a601 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp @@ -720,9 +720,9 @@ void ThrowIfFailed(HRESULT res, HWND h_wnd, const char *message) { } const char* gfx_dxgi_get_key_name(int scancode) { - TCHAR* Text = new TCHAR[64]; - GetKeyNameText(scancode << 16, Text, 64); - return (char*) Text; + static char text[64]; + GetKeyNameTextA(scancode << 16, text, 64); + return text; } extern "C" struct GfxWindowManagerAPI gfx_dxgi_api = { diff --git a/libultraship/libultraship/SDLController.cpp b/libultraship/libultraship/SDLController.cpp index 83f6424e1..97a9a019f 100644 --- a/libultraship/libultraship/SDLController.cpp +++ b/libultraship/libultraship/SDLController.cpp @@ -89,9 +89,6 @@ namespace Ship { ay *= scale; } - ax *= profile->AxisSensitivities[axisX]; - ay *= profile->AxisSensitivities[axisY]; - if (axisX == SDL_CONTROLLER_AXIS_LEFTX) { getLeftStickX(virtualSlot) = +ax; getLeftStickY(virtualSlot) = -ay; @@ -194,7 +191,7 @@ namespace Ship { for (int32_t i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++) { const auto Axis = static_cast(i); - const auto PosScancode = i + AXIS_SCANCODE_BIT; + const auto PosScancode = i | AXIS_SCANCODE_BIT; const auto NegScancode = -PosScancode; const auto AxisDeadzone = profile->AxisDeadzones[i]; const auto AxisMinimumPress = profile->AxisMinimumPress[i]; @@ -217,8 +214,13 @@ namespace Ship { PosButton == BTN_STICKLEFT || PosButton == BTN_STICKRIGHT || PosButton == BTN_STICKUP || PosButton == BTN_STICKDOWN || NegButton == BTN_STICKLEFT || NegButton == BTN_STICKRIGHT || - NegButton == BTN_STICKUP || NegButton == BTN_STICKDOWN)) { + NegButton == BTN_STICKUP || NegButton == BTN_STICKDOWN || + PosButton == BTN_VSTICKLEFT || PosButton == BTN_VSTICKRIGHT || + PosButton == BTN_VSTICKUP || PosButton == BTN_VSTICKDOWN || + NegButton == BTN_VSTICKLEFT || NegButton == BTN_VSTICKRIGHT || + NegButton == BTN_VSTICKUP || NegButton == BTN_VSTICKDOWN)) { + // The axis is being treated as a "button" if (AxisValue > AxisMinimumPress) { getPressedButtons(virtualSlot) |= PosButton; getPressedButtons(virtualSlot) &= ~NegButton; @@ -231,8 +233,10 @@ namespace Ship { getPressedButtons(virtualSlot) &= ~PosButton; getPressedButtons(virtualSlot) &= ~NegButton; } - } - else { + } else { + // The axis is being treated as a "stick" + + // Left stick if (PosButton == BTN_STICKLEFT || PosButton == BTN_STICKRIGHT) { if (LStickAxisX != SDL_CONTROLLER_AXIS_INVALID && LStickAxisX != Axis) { SPDLOG_TRACE("Invalid PosStickX configured. Neg was {} and Pos is {}", LStickAxisX, Axis); @@ -284,30 +288,8 @@ namespace Ship { LStickDeadzone = AxisDeadzone; LStickAxisY = Axis; } - } - // Right Stick - // If the axis is NOT mapped to the control stick. - if (!( - PosButton == BTN_VSTICKLEFT || PosButton == BTN_VSTICKRIGHT || - PosButton == BTN_VSTICKUP || PosButton == BTN_VSTICKDOWN || - NegButton == BTN_VSTICKLEFT || NegButton == BTN_VSTICKRIGHT || - NegButton == BTN_VSTICKUP || NegButton == BTN_VSTICKDOWN)) { - - if (AxisValue > AxisMinimumPress) { - getPressedButtons(virtualSlot) |= PosButton; - getPressedButtons(virtualSlot) &= ~NegButton; - } - else if (AxisValue < -AxisMinimumPress) { - getPressedButtons(virtualSlot) &= ~PosButton; - getPressedButtons(virtualSlot) |= NegButton; - } - else { - getPressedButtons(virtualSlot) &= ~PosButton; - getPressedButtons(virtualSlot) &= ~NegButton; - } - - } else { + // Right Stick if (PosButton == BTN_VSTICKLEFT || PosButton == BTN_VSTICKRIGHT) { if (RStickAxisX != SDL_CONTROLLER_AXIS_INVALID && RStickAxisX != Axis) { SPDLOG_TRACE("Invalid PosStickX configured. Neg was {} and Pos is {}", RStickAxisX, Axis); @@ -359,16 +341,16 @@ namespace Ship { RStickDeadzone = AxisDeadzone; RStickAxisY = Axis; } - - if (LStickAxisX != SDL_CONTROLLER_AXIS_INVALID && LStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { - NormalizeStickAxis(LStickAxisX, LStickAxisY, LStickDeadzone, virtualSlot); - } - - if (RStickAxisX != SDL_CONTROLLER_AXIS_INVALID && RStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { - NormalizeStickAxis(RStickAxisX, RStickAxisY, RStickDeadzone, virtualSlot); - } } } + + if (LStickAxisX != SDL_CONTROLLER_AXIS_INVALID && LStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { + NormalizeStickAxis(LStickAxisX, LStickAxisY, LStickDeadzone, virtualSlot); + } + + if (RStickAxisX != SDL_CONTROLLER_AXIS_INVALID && RStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { + NormalizeStickAxis(RStickAxisX, RStickAxisY, RStickDeadzone, virtualSlot); + } } void SDLController::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) @@ -431,7 +413,11 @@ namespace Ship { void SDLController::CreateDefaultBinding(int32_t virtualSlot) { auto profile = getProfile(virtualSlot); profile->Mappings.clear(); + profile->AxisDeadzones.clear(); + profile->AxisMinimumPress.clear(); + profile->GyroData.clear(); + profile->Version = DEVICE_PROFILE_CURRENT_VERSION; profile->UseRumble = true; profile->RumbleStrength = 1.0f; profile->UseGyro = false; @@ -456,7 +442,6 @@ namespace Ship { profile->Mappings[SDL_CONTROLLER_BUTTON_A] = BTN_A; for (int32_t i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++) { - profile->AxisSensitivities[i] = 1.0f; profile->AxisDeadzones[i] = 16.0f; profile->AxisMinimumPress[i] = 7680.0f; } diff --git a/libultraship/libultraship/WiiUController.cpp b/libultraship/libultraship/WiiUController.cpp index fde41f2cc..cfaa9dbd7 100644 --- a/libultraship/libultraship/WiiUController.cpp +++ b/libultraship/libultraship/WiiUController.cpp @@ -406,14 +406,6 @@ namespace Ship { x *= scale; y *= scale; } - - if (isRightStick) { - getRightStickX(virtualSlot) = x * profile->AxisSensitivities[2]; - getRightStickY(virtualSlot) = y * profile->AxisSensitivities[3]; - } else { - getLeftStickX(virtualSlot) = x * profile->AxisSensitivities[0]; - getLeftStickY(virtualSlot) = y * profile->AxisSensitivities[1]; - } } void WiiUController::CreateDefaultBinding(int32_t virtualSlot) { @@ -484,8 +476,8 @@ namespace Ship { } for (int i = 0; i < 4; i++) { - profile->AxisSensitivities[i] = 1.0f; profile->AxisDeadzones[i] = 0.0f; + profile->AxisMinimumPress[i] = 7680.0f; } } diff --git a/libultraship/libultraship/WiiUGamepad.cpp b/libultraship/libultraship/WiiUGamepad.cpp index 5d4747039..79d41b35f 100644 --- a/libultraship/libultraship/WiiUGamepad.cpp +++ b/libultraship/libultraship/WiiUGamepad.cpp @@ -279,20 +279,13 @@ namespace Ship { x *= scale; y *= scale; } - - if (isRightStick) { - getRightStickX(virtualSlot) = x * profile->AxisSensitivities[2]; - getRightStickY(virtualSlot) = y * profile->AxisSensitivities[3]; - } else { - getLeftStickX(virtualSlot) = x * profile->AxisSensitivities[0]; - getLeftStickY(virtualSlot) = y * profile->AxisSensitivities[1]; - } } void WiiUGamepad::CreateDefaultBinding(int32_t virtualSlot) { auto profile = getProfile(virtualSlot); profile->Mappings.clear(); + profile->Version = DEVICE_PROFILE_CURRENT_VERSION; profile->UseRumble = true; profile->RumbleStrength = 1.0f; profile->UseGyro = false; @@ -317,8 +310,8 @@ namespace Ship { profile->Mappings[VPAD_STICK_L_EMULATION_UP] = BTN_STICKUP; for (int i = 0; i < 4; i++) { - profile->AxisSensitivities[i] = 1.0f; profile->AxisDeadzones[i] = 0.0f; + profile->AxisMinimumPress[i] = 7680.0f; } profile->GyroData[GYRO_SENSITIVITY] = 1.0f;