diff options
| author | 2023-01-28 18:19:15 -0600 | |
|---|---|---|
| committer | 2023-02-01 12:42:05 -0600 | |
| commit | 75e81885b0bd38ece84a94b2d323b05d788f8741 (patch) | |
| tree | c0ed8431e0a29906b41f5a6f74d9f2ddd449e99b | |
| parent | Merge pull request #9707 from german77/clang15 (diff) | |
| download | yuzu-75e81885b0bd38ece84a94b2d323b05d788f8741.tar.gz yuzu-75e81885b0bd38ece84a94b2d323b05d788f8741.tar.xz yuzu-75e81885b0bd38ece84a94b2d323b05d788f8741.zip | |
input_common: Implement turbo buttons
| -rw-r--r-- | src/common/input.h | 2 | ||||
| -rw-r--r-- | src/core/hid/emulated_controller.cpp | 75 | ||||
| -rw-r--r-- | src/core/hid/emulated_controller.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 3 | ||||
| -rw-r--r-- | src/input_common/input_poller.cpp | 30 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_player.cpp | 17 |
6 files changed, 115 insertions, 18 deletions
diff --git a/src/common/input.h b/src/common/input.h index d61cd7ca8..b5748a6c8 100644 --- a/src/common/input.h +++ b/src/common/input.h | |||
| @@ -130,6 +130,8 @@ struct ButtonStatus { | |||
| 130 | bool inverted{}; | 130 | bool inverted{}; |
| 131 | // Press once to activate, press again to release | 131 | // Press once to activate, press again to release |
| 132 | bool toggle{}; | 132 | bool toggle{}; |
| 133 | // Spams the button when active | ||
| 134 | bool turbo{}; | ||
| 133 | // Internal lock for the toggle status | 135 | // Internal lock for the toggle status |
| 134 | bool locked{}; | 136 | bool locked{}; |
| 135 | }; | 137 | }; |
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 0e06468da..631aa6ad2 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | namespace Core::HID { | 12 | namespace Core::HID { |
| 13 | constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | 13 | constexpr s32 HID_JOYSTICK_MAX = 0x7fff; |
| 14 | constexpr s32 HID_TRIGGER_MAX = 0x7fff; | 14 | constexpr s32 HID_TRIGGER_MAX = 0x7fff; |
| 15 | constexpr u32 TURBO_BUTTON_DELAY = 4; | ||
| 15 | // Use a common UUID for TAS and Virtual Gamepad | 16 | // Use a common UUID for TAS and Virtual Gamepad |
| 16 | constexpr Common::UUID TAS_UUID = | 17 | constexpr Common::UUID TAS_UUID = |
| 17 | Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; | 18 | Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; |
| @@ -447,6 +448,7 @@ void EmulatedController::ReloadInput() { | |||
| 447 | }, | 448 | }, |
| 448 | }); | 449 | }); |
| 449 | } | 450 | } |
| 451 | turbo_button_state = 0; | ||
| 450 | } | 452 | } |
| 451 | 453 | ||
| 452 | void EmulatedController::UnloadInput() { | 454 | void EmulatedController::UnloadInput() { |
| @@ -687,6 +689,7 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback | |||
| 687 | } | 689 | } |
| 688 | 690 | ||
| 689 | current_status.toggle = new_status.toggle; | 691 | current_status.toggle = new_status.toggle; |
| 692 | current_status.turbo = new_status.turbo; | ||
| 690 | current_status.uuid = uuid; | 693 | current_status.uuid = uuid; |
| 691 | 694 | ||
| 692 | // Update button status with current | 695 | // Update button status with current |
| @@ -1548,7 +1551,7 @@ NpadButtonState EmulatedController::GetNpadButtons() const { | |||
| 1548 | if (is_configuring) { | 1551 | if (is_configuring) { |
| 1549 | return {}; | 1552 | return {}; |
| 1550 | } | 1553 | } |
| 1551 | return controller.npad_button_state; | 1554 | return {controller.npad_button_state.raw & GetTurboButtonMask()}; |
| 1552 | } | 1555 | } |
| 1553 | 1556 | ||
| 1554 | DebugPadButton EmulatedController::GetDebugPadButtons() const { | 1557 | DebugPadButton EmulatedController::GetDebugPadButtons() const { |
| @@ -1656,4 +1659,74 @@ void EmulatedController::DeleteCallback(int key) { | |||
| 1656 | } | 1659 | } |
| 1657 | callback_list.erase(iterator); | 1660 | callback_list.erase(iterator); |
| 1658 | } | 1661 | } |
| 1662 | |||
| 1663 | void EmulatedController::TurboButtonUpdate() { | ||
| 1664 | turbo_button_state = (turbo_button_state + 1) % (TURBO_BUTTON_DELAY * 2); | ||
| 1665 | } | ||
| 1666 | |||
| 1667 | NpadButton EmulatedController::GetTurboButtonMask() const { | ||
| 1668 | // Apply no mask when disabled | ||
| 1669 | if (turbo_button_state < TURBO_BUTTON_DELAY) { | ||
| 1670 | return {NpadButton::All}; | ||
| 1671 | } | ||
| 1672 | |||
| 1673 | NpadButtonState button_mask{}; | ||
| 1674 | for (std::size_t index = 0; index < controller.button_values.size(); ++index) { | ||
| 1675 | if (!controller.button_values[index].turbo) { | ||
| 1676 | continue; | ||
| 1677 | } | ||
| 1678 | |||
| 1679 | switch (index) { | ||
| 1680 | case Settings::NativeButton::A: | ||
| 1681 | button_mask.a.Assign(1); | ||
| 1682 | break; | ||
| 1683 | case Settings::NativeButton::B: | ||
| 1684 | button_mask.b.Assign(1); | ||
| 1685 | break; | ||
| 1686 | case Settings::NativeButton::X: | ||
| 1687 | button_mask.x.Assign(1); | ||
| 1688 | break; | ||
| 1689 | case Settings::NativeButton::Y: | ||
| 1690 | button_mask.y.Assign(1); | ||
| 1691 | break; | ||
| 1692 | case Settings::NativeButton::L: | ||
| 1693 | button_mask.l.Assign(1); | ||
| 1694 | break; | ||
| 1695 | case Settings::NativeButton::R: | ||
| 1696 | button_mask.r.Assign(1); | ||
| 1697 | break; | ||
| 1698 | case Settings::NativeButton::ZL: | ||
| 1699 | button_mask.zl.Assign(1); | ||
| 1700 | break; | ||
| 1701 | case Settings::NativeButton::ZR: | ||
| 1702 | button_mask.zr.Assign(1); | ||
| 1703 | break; | ||
| 1704 | case Settings::NativeButton::DLeft: | ||
| 1705 | button_mask.left.Assign(1); | ||
| 1706 | break; | ||
| 1707 | case Settings::NativeButton::DUp: | ||
| 1708 | button_mask.up.Assign(1); | ||
| 1709 | break; | ||
| 1710 | case Settings::NativeButton::DRight: | ||
| 1711 | button_mask.right.Assign(1); | ||
| 1712 | break; | ||
| 1713 | case Settings::NativeButton::DDown: | ||
| 1714 | button_mask.down.Assign(1); | ||
| 1715 | break; | ||
| 1716 | case Settings::NativeButton::SL: | ||
| 1717 | button_mask.left_sl.Assign(1); | ||
| 1718 | button_mask.right_sl.Assign(1); | ||
| 1719 | break; | ||
| 1720 | case Settings::NativeButton::SR: | ||
| 1721 | button_mask.left_sr.Assign(1); | ||
| 1722 | button_mask.right_sr.Assign(1); | ||
| 1723 | break; | ||
| 1724 | default: | ||
| 1725 | break; | ||
| 1726 | } | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | return static_cast<NpadButton>(~button_mask.raw); | ||
| 1730 | } | ||
| 1731 | |||
| 1659 | } // namespace Core::HID | 1732 | } // namespace Core::HID |
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 3ac77b2b5..b02bf35c4 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h | |||
| @@ -411,6 +411,9 @@ public: | |||
| 411 | */ | 411 | */ |
| 412 | void DeleteCallback(int key); | 412 | void DeleteCallback(int key); |
| 413 | 413 | ||
| 414 | /// Swaps the state of the turbo buttons | ||
| 415 | void TurboButtonUpdate(); | ||
| 416 | |||
| 414 | private: | 417 | private: |
| 415 | /// creates input devices from params | 418 | /// creates input devices from params |
| 416 | void LoadDevices(); | 419 | void LoadDevices(); |
| @@ -511,6 +514,8 @@ private: | |||
| 511 | */ | 514 | */ |
| 512 | void TriggerOnChange(ControllerTriggerType type, bool is_service_update); | 515 | void TriggerOnChange(ControllerTriggerType type, bool is_service_update); |
| 513 | 516 | ||
| 517 | NpadButton GetTurboButtonMask() const; | ||
| 518 | |||
| 514 | const NpadIdType npad_id_type; | 519 | const NpadIdType npad_id_type; |
| 515 | NpadStyleIndex npad_type{NpadStyleIndex::None}; | 520 | NpadStyleIndex npad_type{NpadStyleIndex::None}; |
| 516 | NpadStyleIndex original_npad_type{NpadStyleIndex::None}; | 521 | NpadStyleIndex original_npad_type{NpadStyleIndex::None}; |
| @@ -520,6 +525,7 @@ private: | |||
| 520 | bool system_buttons_enabled{true}; | 525 | bool system_buttons_enabled{true}; |
| 521 | f32 motion_sensitivity{0.01f}; | 526 | f32 motion_sensitivity{0.01f}; |
| 522 | bool force_update_motion{false}; | 527 | bool force_update_motion{false}; |
| 528 | u32 turbo_button_state{0}; | ||
| 523 | 529 | ||
| 524 | // Temporary values to avoid doing changes while the controller is in configuring mode | 530 | // Temporary values to avoid doing changes while the controller is in configuring mode |
| 525 | NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; | 531 | NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 5713f1288..3afda9e3f 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -428,6 +428,9 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) { | |||
| 428 | return; | 428 | return; |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | // This function is unique to yuzu for the turbo buttons to work properly | ||
| 432 | controller.device->TurboButtonUpdate(); | ||
| 433 | |||
| 431 | auto& pad_entry = controller.npad_pad_state; | 434 | auto& pad_entry = controller.npad_pad_state; |
| 432 | auto& trigger_entry = controller.npad_trigger_state; | 435 | auto& trigger_entry = controller.npad_trigger_state; |
| 433 | const auto button_state = controller.device->GetNpadButtons(); | 436 | const auto button_state = controller.device->GetNpadButtons(); |
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 15cbf7e5f..8c6a6521a 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp | |||
| @@ -16,10 +16,10 @@ public: | |||
| 16 | 16 | ||
| 17 | class InputFromButton final : public Common::Input::InputDevice { | 17 | class InputFromButton final : public Common::Input::InputDevice { |
| 18 | public: | 18 | public: |
| 19 | explicit InputFromButton(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_, | 19 | explicit InputFromButton(PadIdentifier identifier_, int button_, bool turbo_, bool toggle_, |
| 20 | InputEngine* input_engine_) | 20 | bool inverted_, InputEngine* input_engine_) |
| 21 | : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), | 21 | : identifier(identifier_), button(button_), turbo(turbo_), toggle(toggle_), |
| 22 | input_engine(input_engine_) { | 22 | inverted(inverted_), input_engine(input_engine_) { |
| 23 | UpdateCallback engine_callback{[this]() { OnChange(); }}; | 23 | UpdateCallback engine_callback{[this]() { OnChange(); }}; |
| 24 | const InputIdentifier input_identifier{ | 24 | const InputIdentifier input_identifier{ |
| 25 | .identifier = identifier, | 25 | .identifier = identifier, |
| @@ -40,6 +40,7 @@ public: | |||
| 40 | .value = input_engine->GetButton(identifier, button), | 40 | .value = input_engine->GetButton(identifier, button), |
| 41 | .inverted = inverted, | 41 | .inverted = inverted, |
| 42 | .toggle = toggle, | 42 | .toggle = toggle, |
| 43 | .turbo = turbo, | ||
| 43 | }; | 44 | }; |
| 44 | } | 45 | } |
| 45 | 46 | ||
| @@ -68,6 +69,7 @@ public: | |||
| 68 | private: | 69 | private: |
| 69 | const PadIdentifier identifier; | 70 | const PadIdentifier identifier; |
| 70 | const int button; | 71 | const int button; |
| 72 | const bool turbo; | ||
| 71 | const bool toggle; | 73 | const bool toggle; |
| 72 | const bool inverted; | 74 | const bool inverted; |
| 73 | int callback_key; | 75 | int callback_key; |
| @@ -77,10 +79,10 @@ private: | |||
| 77 | 79 | ||
| 78 | class InputFromHatButton final : public Common::Input::InputDevice { | 80 | class InputFromHatButton final : public Common::Input::InputDevice { |
| 79 | public: | 81 | public: |
| 80 | explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool toggle_, | 82 | explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool turbo_, |
| 81 | bool inverted_, InputEngine* input_engine_) | 83 | bool toggle_, bool inverted_, InputEngine* input_engine_) |
| 82 | : identifier(identifier_), button(button_), direction(direction_), toggle(toggle_), | 84 | : identifier(identifier_), button(button_), direction(direction_), turbo(turbo_), |
| 83 | inverted(inverted_), input_engine(input_engine_) { | 85 | toggle(toggle_), inverted(inverted_), input_engine(input_engine_) { |
| 84 | UpdateCallback engine_callback{[this]() { OnChange(); }}; | 86 | UpdateCallback engine_callback{[this]() { OnChange(); }}; |
| 85 | const InputIdentifier input_identifier{ | 87 | const InputIdentifier input_identifier{ |
| 86 | .identifier = identifier, | 88 | .identifier = identifier, |
| @@ -101,6 +103,7 @@ public: | |||
| 101 | .value = input_engine->GetHatButton(identifier, button, direction), | 103 | .value = input_engine->GetHatButton(identifier, button, direction), |
| 102 | .inverted = inverted, | 104 | .inverted = inverted, |
| 103 | .toggle = toggle, | 105 | .toggle = toggle, |
| 106 | .turbo = turbo, | ||
| 104 | }; | 107 | }; |
| 105 | } | 108 | } |
| 106 | 109 | ||
| @@ -130,6 +133,7 @@ private: | |||
| 130 | const PadIdentifier identifier; | 133 | const PadIdentifier identifier; |
| 131 | const int button; | 134 | const int button; |
| 132 | const u8 direction; | 135 | const u8 direction; |
| 136 | const bool turbo; | ||
| 133 | const bool toggle; | 137 | const bool toggle; |
| 134 | const bool inverted; | 138 | const bool inverted; |
| 135 | int callback_key; | 139 | int callback_key; |
| @@ -853,14 +857,15 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateButtonDevice( | |||
| 853 | const auto keyboard_key = params.Get("code", 0); | 857 | const auto keyboard_key = params.Get("code", 0); |
| 854 | const auto toggle = params.Get("toggle", false) != 0; | 858 | const auto toggle = params.Get("toggle", false) != 0; |
| 855 | const auto inverted = params.Get("inverted", false) != 0; | 859 | const auto inverted = params.Get("inverted", false) != 0; |
| 860 | const auto turbo = params.Get("turbo", false) != 0; | ||
| 856 | input_engine->PreSetController(identifier); | 861 | input_engine->PreSetController(identifier); |
| 857 | input_engine->PreSetButton(identifier, button_id); | 862 | input_engine->PreSetButton(identifier, button_id); |
| 858 | input_engine->PreSetButton(identifier, keyboard_key); | 863 | input_engine->PreSetButton(identifier, keyboard_key); |
| 859 | if (keyboard_key != 0) { | 864 | if (keyboard_key != 0) { |
| 860 | return std::make_unique<InputFromButton>(identifier, keyboard_key, toggle, inverted, | 865 | return std::make_unique<InputFromButton>(identifier, keyboard_key, turbo, toggle, inverted, |
| 861 | input_engine.get()); | 866 | input_engine.get()); |
| 862 | } | 867 | } |
| 863 | return std::make_unique<InputFromButton>(identifier, button_id, toggle, inverted, | 868 | return std::make_unique<InputFromButton>(identifier, button_id, turbo, toggle, inverted, |
| 864 | input_engine.get()); | 869 | input_engine.get()); |
| 865 | } | 870 | } |
| 866 | 871 | ||
| @@ -876,11 +881,12 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice( | |||
| 876 | const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); | 881 | const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); |
| 877 | const auto toggle = params.Get("toggle", false) != 0; | 882 | const auto toggle = params.Get("toggle", false) != 0; |
| 878 | const auto inverted = params.Get("inverted", false) != 0; | 883 | const auto inverted = params.Get("inverted", false) != 0; |
| 884 | const auto turbo = params.Get("turbo", false) != 0; | ||
| 879 | 885 | ||
| 880 | input_engine->PreSetController(identifier); | 886 | input_engine->PreSetController(identifier); |
| 881 | input_engine->PreSetHatButton(identifier, button_id); | 887 | input_engine->PreSetHatButton(identifier, button_id); |
| 882 | return std::make_unique<InputFromHatButton>(identifier, button_id, direction, toggle, inverted, | 888 | return std::make_unique<InputFromHatButton>(identifier, button_id, direction, turbo, toggle, |
| 883 | input_engine.get()); | 889 | inverted, input_engine.get()); |
| 884 | } | 890 | } |
| 885 | 891 | ||
| 886 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice( | 892 | std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice( |
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 4b7e3b01b..723690e71 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -182,12 +182,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | |||
| 182 | const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); | 182 | const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); |
| 183 | const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : ""); | 183 | const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : ""); |
| 184 | const QString invert = QString::fromStdString(param.Get("invert", "+") == "-" ? "-" : ""); | 184 | const QString invert = QString::fromStdString(param.Get("invert", "+") == "-" ? "-" : ""); |
| 185 | const QString turbo = QString::fromStdString(param.Get("turbo", false) ? "$" : ""); | ||
| 185 | const auto common_button_name = input_subsystem->GetButtonName(param); | 186 | const auto common_button_name = input_subsystem->GetButtonName(param); |
| 186 | 187 | ||
| 187 | // Retrieve the names from Qt | 188 | // Retrieve the names from Qt |
| 188 | if (param.Get("engine", "") == "keyboard") { | 189 | if (param.Get("engine", "") == "keyboard") { |
| 189 | const QString button_str = GetKeyName(param.Get("code", 0)); | 190 | const QString button_str = GetKeyName(param.Get("code", 0)); |
| 190 | return QObject::tr("%1%2%3").arg(toggle, inverted, button_str); | 191 | return QObject::tr("%1%2%3%4").arg(turbo, toggle, inverted, button_str); |
| 191 | } | 192 | } |
| 192 | 193 | ||
| 193 | if (common_button_name == Common::Input::ButtonNames::Invalid) { | 194 | if (common_button_name == Common::Input::ButtonNames::Invalid) { |
| @@ -201,7 +202,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | |||
| 201 | if (common_button_name == Common::Input::ButtonNames::Value) { | 202 | if (common_button_name == Common::Input::ButtonNames::Value) { |
| 202 | if (param.Has("hat")) { | 203 | if (param.Has("hat")) { |
| 203 | const QString hat = GetDirectionName(param.Get("direction", "")); | 204 | const QString hat = GetDirectionName(param.Get("direction", "")); |
| 204 | return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat); | 205 | return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, hat); |
| 205 | } | 206 | } |
| 206 | if (param.Has("axis")) { | 207 | if (param.Has("axis")) { |
| 207 | const QString axis = QString::fromStdString(param.Get("axis", "")); | 208 | const QString axis = QString::fromStdString(param.Get("axis", "")); |
| @@ -219,13 +220,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | |||
| 219 | } | 220 | } |
| 220 | if (param.Has("button")) { | 221 | if (param.Has("button")) { |
| 221 | const QString button = QString::fromStdString(param.Get("button", "")); | 222 | const QString button = QString::fromStdString(param.Get("button", "")); |
| 222 | return QObject::tr("%1%2Button %3").arg(toggle, inverted, button); | 223 | return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button); |
| 223 | } | 224 | } |
| 224 | } | 225 | } |
| 225 | 226 | ||
| 226 | QString button_name = GetButtonName(common_button_name); | 227 | QString button_name = GetButtonName(common_button_name); |
| 227 | if (param.Has("hat")) { | 228 | if (param.Has("hat")) { |
| 228 | return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name); | 229 | return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, button_name); |
| 229 | } | 230 | } |
| 230 | if (param.Has("axis")) { | 231 | if (param.Has("axis")) { |
| 231 | return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); | 232 | return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); |
| @@ -234,7 +235,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | |||
| 234 | return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); | 235 | return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); |
| 235 | } | 236 | } |
| 236 | if (param.Has("button")) { | 237 | if (param.Has("button")) { |
| 237 | return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name); | 238 | return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button_name); |
| 238 | } | 239 | } |
| 239 | 240 | ||
| 240 | return QObject::tr("[unknown]"); | 241 | return QObject::tr("[unknown]"); |
| @@ -395,6 +396,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 395 | button_map[button_id]->setText(ButtonToText(param)); | 396 | button_map[button_id]->setText(ButtonToText(param)); |
| 396 | emulated_controller->SetButtonParam(button_id, param); | 397 | emulated_controller->SetButtonParam(button_id, param); |
| 397 | }); | 398 | }); |
| 399 | context_menu.addAction(tr("Turbo button"), [&] { | ||
| 400 | const bool turbo_value = !param.Get("turbo", false); | ||
| 401 | param.Set("turbo", turbo_value); | ||
| 402 | button_map[button_id]->setText(ButtonToText(param)); | ||
| 403 | emulated_controller->SetButtonParam(button_id, param); | ||
| 404 | }); | ||
| 398 | } | 405 | } |
| 399 | if (param.Has("axis")) { | 406 | if (param.Has("axis")) { |
| 400 | context_menu.addAction(tr("Invert axis"), [&] { | 407 | context_menu.addAction(tr("Invert axis"), [&] { |