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.
This commit is contained in:
Kenix3 2022-08-16 21:53:45 -04:00 committed by GitHub
parent 6b0338a37d
commit d09172d74d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 104 additions and 123 deletions

View File

@ -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<SDLController>(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<Ship::WiiUController>((WPADChan) i);
controller->Open();
physicalDevices.push_back(controller);
@ -53,20 +53,20 @@ namespace Ship {
physicalDevices.push_back(std::make_shared<DummyController>("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<int>(physicalDevices.size()) - 1);
}
LoadControllerSettings();
}
void ControlDeck::SetPhysicalDevice(int slot, int deviceSlot) {
void ControlDeck::SetPhysicalDevice(int32_t slot, int32_t deviceSlot) {
const std::shared_ptr<Controller> backend = physicalDevices[deviceSlot];
virtualDevices[slot] = deviceSlot;
*controllerBits |= (backend->Connected()) << slot;
@ -104,7 +104,7 @@ namespace Ship {
std::shared_ptr<Mercury> 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<Controller> ControlDeck::GetPhysicalDevice(int deviceSlot) {
std::shared_ptr<Controller> 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<Controller> ControlDeck::GetPhysicalDeviceFromVirtualSlot(int slot) {
std::shared_ptr<Controller> ControlDeck::GetPhysicalDeviceFromVirtualSlot(int32_t slot) {
return GetPhysicalDevice(GetVirtualDevice(slot));
}

View File

@ -2,6 +2,7 @@
#include "Controller.h"
#include <vector>
#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<Ship::Controller> GetPhysicalDevice(int deviceSlot);
std::shared_ptr<Ship::Controller> GetPhysicalDeviceFromVirtualSlot(int slot);
void SetPhysicalDevice(int32_t slot, int32_t deviceSlot);
std::shared_ptr<Controller> GetPhysicalDevice(int32_t deviceSlot);
std::shared_ptr<Controller> GetPhysicalDeviceFromVirtualSlot(int32_t slot);
size_t GetNumPhysicalDevices();
int GetVirtualDevice(int slot);
int32_t GetVirtualDevice(int32_t slot);
size_t GetNumVirtualDevices();
uint8_t* GetControllerBits();
private:

View File

@ -13,7 +13,7 @@ namespace Ship {
Attachment = nullptr;
for(int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) {
profiles[virtualSlot] = std::make_shared<DeviceProfileV0>();
profiles[virtualSlot] = std::make_shared<DeviceProfile>();
ButtonData[virtualSlot] = std::make_shared<Buttons>();
}
}
@ -109,7 +109,7 @@ namespace Ship {
return ButtonData[virtualSlot]->gyroY;
}
std::shared_ptr<DeviceProfileV0> Controller::getProfile(int32_t virtualSlot) {
std::shared_ptr<DeviceProfile> Controller::getProfile(int32_t virtualSlot) {
return profiles[virtualSlot];
}
}

View File

@ -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<int32_t, float> AxisDeadzones;
std::unordered_map<int32_t, float> AxisMinimumPress;
std::unordered_map<int32_t, float> AxisSensitivities;
std::unordered_map<int32_t, float> GyroData;
std::map<int32_t, int32_t> 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<DeviceProfileV0> getProfile(int32_t virtualSlot);
std::shared_ptr<DeviceProfile> 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<int32_t, std::shared_ptr<DeviceProfileV0>> profiles;
std::unordered_map<int32_t, std::shared_ptr<DeviceProfile>> profiles;
std::unordered_map<int32_t, std::shared_ptr<Buttons>> ButtonData = {};
};
}

View File

@ -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);

View File

@ -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 = {

View File

@ -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<SDL_GameControllerAxis>(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;
}

View File

@ -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;
}
}

View File

@ -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;