diff --git a/src/controller/ControlDeck.cpp b/src/controller/ControlDeck.cpp index 0fd9a1af6..839da069e 100644 --- a/src/controller/ControlDeck.cpp +++ b/src/controller/ControlDeck.cpp @@ -209,6 +209,7 @@ void ControlDeck::LoadSettings() { profile->RumbleStrength = config->GetFloat(NESTED("Rumble.Strength", "")); profile->UseGyro = config->GetBool(NESTED("Gyro.Enabled", "")); profile->NotchProximityThreshold = config->GetInt(NESTED("Notches.ProximityThreshold", "")); + profile->UseStickDeadzoneForButtons = config->GetBool(NESTED("UseStickDeadzoneForButtons", "")); for (auto const& val : rawProfile["AxisDeadzones"].items()) { profile->AxisDeadzones[std::stoi(val.key())] = val.value(); @@ -265,6 +266,7 @@ void ControlDeck::SaveSettings() { config->SetFloat(NESTED("Rumble.Strength", ""), profile->RumbleStrength); config->SetBool(NESTED("Gyro.Enabled", ""), profile->UseGyro); config->SetInt(NESTED("Notches.ProximityThreshold", ""), profile->NotchProximityThreshold); + config->SetBool(NESTED("UseStickDeadzoneForButtons", ""), profile->UseStickDeadzoneForButtons); // Clear all sections with a one controller to many relationship. const static std::vector sClearSections = { "Mappings", "AxisDeadzones", "AxisMinimumPress", diff --git a/src/controller/Controller.h b/src/controller/Controller.h index 176fc6a73..695c38d71 100644 --- a/src/controller/Controller.h +++ b/src/controller/Controller.h @@ -25,6 +25,7 @@ struct DeviceProfile { int32_t Version = 0; bool UseRumble = false; bool UseGyro = false; + bool UseStickDeadzoneForButtons = false; float RumbleStrength = 1.0f; int32_t NotchProximityThreshold = 0; std::unordered_map AxisDeadzones; diff --git a/src/controller/SDLController.cpp b/src/controller/SDLController.cpp index 8538a1be1..5f6c8b2bb 100644 --- a/src/controller/SDLController.cpp +++ b/src/controller/SDLController.cpp @@ -62,13 +62,17 @@ bool SDLController::Close() { return true; } +float SDLController::NormaliseStickValue(float axisValue) { + // scale {-32768 ... +32767} to {-MAX_AXIS_RANGE ... +MAX_AXIS_RANGE} + return axisValue * MAX_AXIS_RANGE / MAX_SDL_RANGE; +} + void SDLController::NormalizeStickAxis(SDL_GameControllerAxis axisX, SDL_GameControllerAxis axisY, int32_t portIndex) { const auto axisValueX = SDL_GameControllerGetAxis(mController, axisX); const auto axisValueY = SDL_GameControllerGetAxis(mController, axisY); - // scale {-32768 ... +32767} to {-MAX_AXIS_RANGE ... +MAX_AXIS_RANGE} - auto ax = axisValueX * MAX_AXIS_RANGE / MAX_SDL_RANGE; - auto ay = axisValueY * MAX_AXIS_RANGE / MAX_SDL_RANGE; + auto ax = NormaliseStickValue(axisValueX); + auto ay = NormaliseStickValue(axisValueY); if (axisX == SDL_CONTROLLER_AXIS_LEFTX) { GetLeftStickX(portIndex) = +ax; @@ -175,6 +179,7 @@ void SDLController::ReadDevice(int32_t portIndex) { const auto posScancode = i | AXIS_SCANCODE_BIT; const auto negScancode = -posScancode; const auto axisMinimumPress = profile->AxisMinimumPress[i]; + const auto axisDeadzone = profile->AxisDeadzones[i]; const auto posButton = profile->Mappings[posScancode]; const auto negButton = profile->Mappings[negScancode]; const auto axisValue = SDL_GameControllerGetAxis(mController, axis); @@ -198,10 +203,18 @@ void SDLController::ReadDevice(int32_t portIndex) { negButton == BTN_VSTICKDOWN)) { // The axis is being treated as a "button" - if (axisValue > axisMinimumPress) { + + auto axisComparableValue = axisValue; + auto axisMinValue = axisMinimumPress; + if (profile->UseStickDeadzoneForButtons) { + axisComparableValue = NormaliseStickValue(axisValue); + axisMinValue = axisDeadzone; + } + + if (axisComparableValue > axisMinValue) { GetPressedButtons(portIndex) |= posButton; GetPressedButtons(portIndex) &= ~negButton; - } else if (axisValue < -axisMinimumPress) { + } else if (axisComparableValue < -axisMinValue) { GetPressedButtons(portIndex) &= ~posButton; GetPressedButtons(portIndex) |= negButton; } else { diff --git a/src/controller/SDLController.h b/src/controller/SDLController.h index 05d4f5120..d9739bd57 100644 --- a/src/controller/SDLController.h +++ b/src/controller/SDLController.h @@ -27,6 +27,7 @@ class SDLController : public Controller { private: SDL_GameController* mController; bool mSupportsGyro; + float NormaliseStickValue(float axisValue); void NormalizeStickAxis(SDL_GameControllerAxis axisX, SDL_GameControllerAxis axisY, int32_t portIndex); bool Close(); }; diff --git a/src/window/gui/InputEditorWindow.cpp b/src/window/gui/InputEditorWindow.cpp index 2bdb5cf3d..40292e883 100644 --- a/src/window/gui/InputEditorWindow.cpp +++ b/src/window/gui/InputEditorWindow.cpp @@ -377,16 +377,15 @@ void InputEditorWindow::DrawControllerSchema() { DrawButton("Left", BTN_CLEFT, mCurrentPort, &mBtnReading); DrawButton("Right", BTN_CRIGHT, mCurrentPort, &mBtnReading); ImGui::Dummy(ImVec2(0, 5)); - EndGroupPanel(0.0f); - - ImGui::SetCursorPosX(cursor.x); #ifdef __SWITCH__ - ImGui::SetCursorPosY(cursor.y + 167); -#elif defined(__WIIU__) - ImGui::SetCursorPosY(cursor.y + 120 * 2); + EndGroupPanel(isKeyboard ? 53.0f : 122.0f); #else - ImGui::SetCursorPosY(cursor.y + 120); + EndGroupPanel(isKeyboard ? 53.0f : 94.0f); #endif + + ImGui::SetCursorPosX(cursor.x); + ImGui::SameLine(); + BeginGroupPanel("Options", ImVec2(158, 20)); float cursorX = ImGui::GetCursorPosX() + 5; ImGui::SetCursorPosX(cursorX); @@ -427,6 +426,13 @@ void InputEditorWindow::DrawControllerSchema() { ImGui::SetTooltip( "%s", "How near in degrees to a virtual notch angle you have to be for it to snap to nearest notch"); } + + if (ImGui::Checkbox("Stick Deadzones For Buttons", &profile->UseStickDeadzoneForButtons)) { + Context::GetInstance()->GetControlDeck()->SaveSettings(); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s", "Uses the stick deadzone values when sticks are mapped to buttons"); + } } ImGui::Dummy(ImVec2(0, 5));