From 164c043e1b45be7e7ada43411e3d79628fdc5a4a Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 22 Oct 2024 19:39:56 +1000 Subject: [PATCH] InputManager: Add pressure/deadzone to macros Arguably less useful than on the PS2, but is still applicable to the left/right analog sticks. --- src/core/fullscreen_ui.cpp | 69 ++++++----- .../controllerbindingwidgets.cpp | 21 ++++ src/duckstation-qt/controllerbindingwidgets.h | 2 + .../controllermacroeditwidget.ui | 110 ++++++++++++++++-- src/util/imgui_glyph_ranges.inl | 2 +- src/util/input_manager.cpp | 21 +++- 6 files changed, 184 insertions(+), 41 deletions(-) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index d265e976b..d20e71a69 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -3815,16 +3815,10 @@ void FullscreenUI::DrawControllerSettingsPage() continue; DrawInputBindingButton(bsi, InputBindingInfo::Type::Macro, section.c_str(), - TinyString::from_format("Macro{}", macro_index + 1), - TinyString::from_format(FSUI_FSTR("Macro {} Trigger"), macro_index + 1), nullptr); - DrawToggleSetting(bsi, - TinyString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_GAMEPAD, "Macro {} Press To Toggle")), - macro_index + 1), - nullptr, section.c_str(), TinyString::from_format("Macro{}Toggle", macro_index + 1), false, - true, false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); + TinyString::from_format("Macro{}", macro_index + 1), FSUI_CSTR("Trigger"), nullptr, true); SmallString binds_string = - bsi->GetSmallStringValue(section.c_str(), fmt::format("Macro{}Binds", macro_index + 1).c_str()); + bsi->GetSmallStringValue(section.c_str(), TinyString::from_format("Macro{}Binds", macro_index + 1).c_str()); TinyString pretty_binds_string; if (!binds_string.empty()) { @@ -3842,10 +3836,9 @@ void FullscreenUI::DrawControllerSettingsPage() pretty_binds_string.append_format("{}{}", pretty_binds_string.empty() ? "" : " ", dispname); } } - if (MenuButtonWithValue( - TinyString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_KEYBOARD, "Macro {} Buttons")), macro_index + 1), - nullptr, pretty_binds_string.empty() ? FSUI_CSTR("-") : pretty_binds_string.c_str(), true, - LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY)) + if (MenuButtonWithValue(FSUI_ICONSTR(ICON_FA_KEYBOARD, "Buttons"), nullptr, + pretty_binds_string.empty() ? FSUI_CSTR("-") : pretty_binds_string.c_str(), true, + LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY)) { std::vector buttons_split(StringUtil::SplitString(binds_string, '&', true)); ImGuiFullscreen::ChoiceDialogOptions options; @@ -3906,19 +3899,37 @@ void FullscreenUI::DrawControllerSettingsPage() }); } + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_GAMEPAD, "Press To Toggle"), + FSUI_CSTR("Toggles the macro when the button is pressed, instead of held."), section.c_str(), + TinyString::from_format("Macro{}Toggle", macro_index + 1), false, true, false); + const TinyString freq_key = TinyString::from_format("Macro{}Frequency", macro_index + 1); - const SmallString freq_title = - SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_LIGHTBULB, "Macro {} Frequency")), macro_index + 1); + const TinyString freq_label = + TinyString::from_format(ICON_FA_CLOCK " {}##macro_{}_frequency", FSUI_VSTR("Frequency"), macro_index + 1); s32 frequency = bsi->GetIntValue(section.c_str(), freq_key.c_str(), 0); - SmallString freq_summary; - if (frequency == 0) - freq_summary = FSUI_VSTR("Disabled"); - else - freq_summary.format(FSUI_FSTR("{} Frames"), frequency); - if (MenuButtonWithValue(freq_title, nullptr, freq_summary, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY)) - ImGui::OpenPopup(freq_title); + const TinyString freq_summary = ((frequency == 0) ? TinyString(FSUI_VSTR("Disabled")) : + TinyString::from_format(FSUI_FSTR("{} Frames"), frequency)); + if (MenuButtonWithValue( + freq_label, + FSUI_CSTR( + "Determines the frequency at which the macro will toggle the buttons on and off (aka auto fire)."), + freq_summary, true)) + { + ImGui::OpenPopup(freq_label.c_str()); + } + + DrawFloatSpinBoxSetting(bsi, FSUI_ICONSTR(ICON_FA_ARROW_DOWN, "Pressure"), + FSUI_CSTR("Determines how much pressure is simulated when macro is active."), section, + TinyString::from_format("Macro{}Pressure", macro_index + 1), 1.0f, 0.01f, 1.0f, 0.01f, + 100.0f, "%.0f%%"); + + DrawFloatSpinBoxSetting(bsi, FSUI_ICONSTR(ICON_FA_SKULL, "Deadzone"), + FSUI_CSTR("Determines how much button pressure is ignored before activating the macro."), + section, TinyString::from_format("Macro{}Deadzone", macro_index + 1).c_str(), 0.0f, 0.00f, + 1.0f, 0.01f, 100.0f, "%.0f%%"); ImGui::SetNextWindowSize(LayoutScale(500.0f, 180.0f)); + ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::PushFont(g_large_font); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); @@ -3926,7 +3937,7 @@ void FullscreenUI::DrawControllerSettingsPage() ImGuiFullscreen::LAYOUT_MENU_BUTTON_Y_PADDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); - if (ImGui::BeginPopupModal(freq_title, nullptr, + if (ImGui::BeginPopupModal(freq_label, nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove)) { ImGui::SetNextItemWidth(LayoutScale(450.0f)); @@ -7445,6 +7456,7 @@ TRANSLATE_NOOP("FullscreenUI", "Backend Settings"); TRANSLATE_NOOP("FullscreenUI", "Behavior"); TRANSLATE_NOOP("FullscreenUI", "Borderless Fullscreen"); TRANSLATE_NOOP("FullscreenUI", "Buffer Size"); +TRANSLATE_NOOP("FullscreenUI", "Buttons"); TRANSLATE_NOOP("FullscreenUI", "CD-ROM Emulation"); TRANSLATE_NOOP("FullscreenUI", "CPU Emulation"); TRANSLATE_NOOP("FullscreenUI", "CPU Mode"); @@ -7496,6 +7508,7 @@ TRANSLATE_NOOP("FullscreenUI", "Create Save State Backups"); TRANSLATE_NOOP("FullscreenUI", "Crop Mode"); TRANSLATE_NOOP("FullscreenUI", "Culling Correction"); TRANSLATE_NOOP("FullscreenUI", "Current Game"); +TRANSLATE_NOOP("FullscreenUI", "Deadzone"); TRANSLATE_NOOP("FullscreenUI", "Debugging Settings"); TRANSLATE_NOOP("FullscreenUI", "Default"); TRANSLATE_NOOP("FullscreenUI", "Default Boot"); @@ -7510,8 +7523,10 @@ TRANSLATE_NOOP("FullscreenUI", "Desktop Mode"); TRANSLATE_NOOP("FullscreenUI", "Details"); TRANSLATE_NOOP("FullscreenUI", "Details unavailable for game not scanned in game list."); TRANSLATE_NOOP("FullscreenUI", "Determines how large the on-screen messages and monitor are."); +TRANSLATE_NOOP("FullscreenUI", "Determines how much button pressure is ignored before activating the macro."); TRANSLATE_NOOP("FullscreenUI", "Determines how much latency there is between the audio being picked up by the host API, and played through speakers."); TRANSLATE_NOOP("FullscreenUI", "Determines how much of the area typically not visible on a consumer TV set to crop/hide."); +TRANSLATE_NOOP("FullscreenUI", "Determines how much pressure is simulated when macro is active."); TRANSLATE_NOOP("FullscreenUI", "Determines how the emulated CPU executes instructions."); TRANSLATE_NOOP("FullscreenUI", "Determines how the emulated console's output is upscaled or downscaled to your monitor's resolution."); TRANSLATE_NOOP("FullscreenUI", "Determines quality of audio when not running at 100% speed."); @@ -7519,6 +7534,7 @@ TRANSLATE_NOOP("FullscreenUI", "Determines that field that the game list will be TRANSLATE_NOOP("FullscreenUI", "Determines the amount of audio buffered before being pulled by the host API."); TRANSLATE_NOOP("FullscreenUI", "Determines the emulated hardware type."); TRANSLATE_NOOP("FullscreenUI", "Determines the format that screenshots will be saved/compressed with."); +TRANSLATE_NOOP("FullscreenUI", "Determines the frequency at which the macro will toggle the buttons on and off (aka auto fire)."); TRANSLATE_NOOP("FullscreenUI", "Determines the margin between the edge of the screen and on-screen messages."); TRANSLATE_NOOP("FullscreenUI", "Determines the position on the screen when black borders must be added."); TRANSLATE_NOOP("FullscreenUI", "Determines the rotation of the simulated TV screen."); @@ -7616,6 +7632,7 @@ TRANSLATE_NOOP("FullscreenUI", "Forces blending to be done in the shader at 16-b TRANSLATE_NOOP("FullscreenUI", "Forces the use of FIFO over Mailbox presentation, i.e. double buffering instead of triple buffering. Usually results in worse frame pacing."); TRANSLATE_NOOP("FullscreenUI", "Forcibly mutes both CD-DA and XA audio from the CD-ROM. Can be used to disable background music in some games."); TRANSLATE_NOOP("FullscreenUI", "Frame Time Buffer"); +TRANSLATE_NOOP("FullscreenUI", "Frequency"); TRANSLATE_NOOP("FullscreenUI", "From File..."); TRANSLATE_NOOP("FullscreenUI", "Fullscreen Resolution"); TRANSLATE_NOOP("FullscreenUI", "GPU Adapter"); @@ -7700,10 +7717,6 @@ TRANSLATE_NOOP("FullscreenUI", "Logs messages to the console window."); TRANSLATE_NOOP("FullscreenUI", "Logs messages to the debug console where supported."); TRANSLATE_NOOP("FullscreenUI", "Logs out of RetroAchievements."); TRANSLATE_NOOP("FullscreenUI", "Macro Button {}"); -TRANSLATE_NOOP("FullscreenUI", "Macro {} Buttons"); -TRANSLATE_NOOP("FullscreenUI", "Macro {} Frequency"); -TRANSLATE_NOOP("FullscreenUI", "Macro {} Press To Toggle"); -TRANSLATE_NOOP("FullscreenUI", "Macro {} Trigger"); TRANSLATE_NOOP("FullscreenUI", "Makes games run closer to their console framerate, at a small cost to performance."); TRANSLATE_NOOP("FullscreenUI", "Memory Card Busy"); TRANSLATE_NOOP("FullscreenUI", "Memory Card Directory"); @@ -7773,6 +7786,8 @@ TRANSLATE_NOOP("FullscreenUI", "Post-processing shaders reloaded."); TRANSLATE_NOOP("FullscreenUI", "Preload Images to RAM"); TRANSLATE_NOOP("FullscreenUI", "Preload Replacement Textures"); TRANSLATE_NOOP("FullscreenUI", "Preserve Projection Precision"); +TRANSLATE_NOOP("FullscreenUI", "Press To Toggle"); +TRANSLATE_NOOP("FullscreenUI", "Pressure"); TRANSLATE_NOOP("FullscreenUI", "Prevents the emulator from producing any audible sound."); TRANSLATE_NOOP("FullscreenUI", "Prevents the screen saver from activating and the host from sleeping while emulation is running."); TRANSLATE_NOOP("FullscreenUI", "Provides vibration and LED control support over Bluetooth."); @@ -7962,6 +7977,8 @@ TRANSLATE_NOOP("FullscreenUI", "Toggle Analog"); TRANSLATE_NOOP("FullscreenUI", "Toggle Fast Forward"); TRANSLATE_NOOP("FullscreenUI", "Toggle Fullscreen"); TRANSLATE_NOOP("FullscreenUI", "Toggle every %d frames"); +TRANSLATE_NOOP("FullscreenUI", "Toggles the macro when the button is pressed, instead of held."); +TRANSLATE_NOOP("FullscreenUI", "Trigger"); TRANSLATE_NOOP("FullscreenUI", "True Color Rendering"); TRANSLATE_NOOP("FullscreenUI", "Turbo Speed"); TRANSLATE_NOOP("FullscreenUI", "Type"); diff --git a/src/duckstation-qt/controllerbindingwidgets.cpp b/src/duckstation-qt/controllerbindingwidgets.cpp index fbaa8c2d9..fc75b7ca6 100644 --- a/src/duckstation-qt/controllerbindingwidgets.cpp +++ b/src/duckstation-qt/controllerbindingwidgets.cpp @@ -605,6 +605,17 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare m_ui.bindList->addItem(item); } + ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized( + dialog->getEditingSettingsInterface(), m_ui.pressure, section, fmt::format("Macro{}Pressure", index + 1u), 100.0f, + 1.0f); + ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized( + dialog->getEditingSettingsInterface(), m_ui.deadzone, section, fmt::format("Macro{}Deadzone", index + 1u), 100.0f, + 0.0f); + connect(m_ui.pressure, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onPressureChanged); + connect(m_ui.deadzone, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onDeadzoneChanged); + onPressureChanged(); + onDeadzoneChanged(); + m_frequency = dialog->getIntValue(section.c_str(), TinyString::from_format("Macro{}Frequency", index + 1u), 0); ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(dialog->getEditingSettingsInterface(), m_ui.triggerToggle, section.c_str(), fmt::format("Macro{}Toggle", index + 1u), @@ -634,6 +645,16 @@ QString ControllerMacroEditWidget::getSummary() const return str.empty() ? tr("Not Configured") : QString::fromUtf8(str.c_str(), static_cast(str.length())); } +void ControllerMacroEditWidget::onPressureChanged() +{ + m_ui.pressureValue->setText(tr("%1%").arg(m_ui.pressure->value())); +} + +void ControllerMacroEditWidget::onDeadzoneChanged() +{ + m_ui.deadzoneValue->setText(tr("%1%").arg(m_ui.deadzone->value())); +} + void ControllerMacroEditWidget::onSetFrequencyClicked() { bool okay; diff --git a/src/duckstation-qt/controllerbindingwidgets.h b/src/duckstation-qt/controllerbindingwidgets.h index 012f55312..0284b078a 100644 --- a/src/duckstation-qt/controllerbindingwidgets.h +++ b/src/duckstation-qt/controllerbindingwidgets.h @@ -103,6 +103,8 @@ public: QString getSummary() const; private Q_SLOTS: + void onPressureChanged(); + void onDeadzoneChanged(); void onSetFrequencyClicked(); void updateBinds(); diff --git a/src/duckstation-qt/controllermacroeditwidget.ui b/src/duckstation-qt/controllermacroeditwidget.ui index d4f051c2e..2b4757d99 100644 --- a/src/duckstation-qt/controllermacroeditwidget.ui +++ b/src/duckstation-qt/controllermacroeditwidget.ui @@ -6,8 +6,8 @@ 0 0 - 664 - 420 + 691 + 433 @@ -29,6 +29,9 @@ Binds/Buttons + + + @@ -39,8 +42,57 @@ - - + + + + + + + Pressure + + + + + + For buttons which are pressure sensitive, this slider controls how much force will be simulated when the macro is active. + + + true + + + + + + + + + 1 + + + 100 + + + 100 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + + + + + 100% + + + + @@ -51,10 +103,10 @@ Trigger - + - + Select the trigger to activate this macro. This can be a single button, or combination of buttons (chord). Shift-click for multiple triggers. @@ -67,7 +119,7 @@ - + Press To Toggle @@ -75,13 +127,53 @@ - + - PushButton + PushButton + + + + + + Deadzone: + + + + + + + 0 + + + 100 + + + 100 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + + + + + 100% + + + + + diff --git a/src/util/imgui_glyph_ranges.inl b/src/util/imgui_glyph_ranges.inl index 03331256a..aa383e276 100644 --- a/src/util/imgui_glyph_ranges.inl +++ b/src/util/imgui_glyph_ranges.inl @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 -static constexpr ImWchar FA_ICON_RANGE[] = { 0xe06f,0xe06f,0xe086,0xe086,0xf002,0xf002,0xf005,0xf005,0xf007,0xf007,0xf00c,0xf00e,0xf011,0xf011,0xf013,0xf013,0xf017,0xf017,0xf019,0xf019,0xf01c,0xf01c,0xf021,0xf021,0xf023,0xf023,0xf025,0xf025,0xf02e,0xf02e,0xf030,0xf030,0xf03a,0xf03a,0xf03d,0xf03d,0xf04a,0xf04c,0xf050,0xf050,0xf05e,0xf05e,0xf062,0xf063,0xf067,0xf067,0xf071,0xf071,0xf075,0xf075,0xf077,0xf078,0xf07b,0xf07c,0xf084,0xf085,0xf091,0xf091,0xf0ac,0xf0ad,0xf0c3,0xf0c3,0xf0c5,0xf0c5,0xf0c7,0xf0c9,0xf0cb,0xf0cb,0xf0d0,0xf0d0,0xf0dc,0xf0dc,0xf0e2,0xf0e2,0xf0e7,0xf0e7,0xf0eb,0xf0eb,0xf0f1,0xf0f1,0xf0f3,0xf0f3,0xf0fe,0xf0fe,0xf110,0xf110,0xf119,0xf119,0xf11b,0xf11c,0xf140,0xf140,0xf14a,0xf14a,0xf15b,0xf15b,0xf15d,0xf15d,0xf191,0xf192,0xf1ab,0xf1ab,0xf1dd,0xf1de,0xf1e6,0xf1e6,0xf1eb,0xf1eb,0xf1f8,0xf1f8,0xf1fc,0xf1fc,0xf240,0xf240,0xf242,0xf242,0xf245,0xf245,0xf26c,0xf26c,0xf279,0xf279,0xf2d0,0xf2d0,0xf2db,0xf2db,0xf2f2,0xf2f2,0xf3fd,0xf3fd,0xf410,0xf410,0xf462,0xf462,0xf466,0xf466,0xf4ce,0xf4ce,0xf500,0xf500,0xf51f,0xf51f,0xf538,0xf538,0xf545,0xf545,0xf547,0xf548,0xf5a2,0xf5a2,0xf5aa,0xf5aa,0xf5e7,0xf5e7,0xf65d,0xf65e,0xf6cf,0xf6cf,0xf70c,0xf70c,0xf794,0xf794,0xf7a0,0xf7a0,0xf7c2,0xf7c2,0xf807,0xf807,0xf815,0xf815,0xf818,0xf818,0xf84c,0xf84c,0xf8cc,0xf8cc,0x0,0x0 }; +static constexpr ImWchar FA_ICON_RANGE[] = { 0xe06f,0xe06f,0xe086,0xe086,0xf002,0xf002,0xf005,0xf005,0xf007,0xf007,0xf00c,0xf00e,0xf011,0xf011,0xf013,0xf013,0xf017,0xf017,0xf019,0xf019,0xf01c,0xf01c,0xf021,0xf021,0xf023,0xf023,0xf025,0xf025,0xf02e,0xf02e,0xf030,0xf030,0xf03a,0xf03a,0xf03d,0xf03d,0xf04a,0xf04c,0xf050,0xf050,0xf05e,0xf05e,0xf062,0xf063,0xf067,0xf067,0xf071,0xf071,0xf075,0xf075,0xf077,0xf078,0xf07b,0xf07c,0xf084,0xf085,0xf091,0xf091,0xf0ac,0xf0ad,0xf0c3,0xf0c3,0xf0c5,0xf0c5,0xf0c7,0xf0c9,0xf0cb,0xf0cb,0xf0d0,0xf0d0,0xf0dc,0xf0dc,0xf0e2,0xf0e2,0xf0e7,0xf0e7,0xf0eb,0xf0eb,0xf0f1,0xf0f1,0xf0f3,0xf0f3,0xf0fe,0xf0fe,0xf110,0xf110,0xf119,0xf119,0xf11b,0xf11c,0xf140,0xf140,0xf14a,0xf14a,0xf15b,0xf15b,0xf15d,0xf15d,0xf191,0xf192,0xf1ab,0xf1ab,0xf1dd,0xf1de,0xf1e6,0xf1e6,0xf1eb,0xf1eb,0xf1f8,0xf1f8,0xf1fc,0xf1fc,0xf240,0xf240,0xf242,0xf242,0xf245,0xf245,0xf26c,0xf26c,0xf279,0xf279,0xf2d0,0xf2d0,0xf2db,0xf2db,0xf2f2,0xf2f2,0xf3fd,0xf3fd,0xf410,0xf410,0xf462,0xf462,0xf466,0xf466,0xf4ce,0xf4ce,0xf500,0xf500,0xf51f,0xf51f,0xf538,0xf538,0xf545,0xf545,0xf547,0xf548,0xf54c,0xf54c,0xf5a2,0xf5a2,0xf5aa,0xf5aa,0xf5e7,0xf5e7,0xf65d,0xf65e,0xf6cf,0xf6cf,0xf70c,0xf70c,0xf794,0xf794,0xf7a0,0xf7a0,0xf7c2,0xf7c2,0xf807,0xf807,0xf815,0xf815,0xf818,0xf818,0xf84c,0xf84c,0xf8cc,0xf8cc,0x0,0x0 }; static constexpr ImWchar PF_ICON_RANGE[] = { 0x2196,0x2199,0x219e,0x21a1,0x21b0,0x21b3,0x21ba,0x21c3,0x21c7,0x21ca,0x21d0,0x21d4,0x21dc,0x21dd,0x21e0,0x21e3,0x21ed,0x21ee,0x21f7,0x21f8,0x21fa,0x21fb,0x227a,0x227f,0x2284,0x2284,0x2349,0x2349,0x235e,0x235e,0x2360,0x2361,0x2364,0x2366,0x23b2,0x23b4,0x23ce,0x23ce,0x23f4,0x23f7,0x2427,0x243a,0x243c,0x243e,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24fd,0x24ff,0x24ff,0x2717,0x2717,0x278a,0x278e,0x27fc,0x27fc,0xe001,0xe001,0xff21,0xff3a,0x1f52b,0x1f52b,0x0,0x0 }; diff --git a/src/util/input_manager.cpp b/src/util/input_manager.cpp index 40383baa9..e7c63f21c 100644 --- a/src/util/input_manager.cpp +++ b/src/util/input_manager.cpp @@ -92,6 +92,7 @@ struct MacroButton bool toggle_state; ///< Current state for turbo. bool trigger_state; ///< Whether the macro button is active. bool trigger_toggle; ///< Whether the macro is trigged by holding or press. + u8 trigger_pressure; ///< Pressure to apply when macro is active. }; } // namespace @@ -898,10 +899,13 @@ void InputManager::AddPadBindings(const SettingsInterface& si, const std::string si.GetStringList(section.c_str(), fmt::format("Macro{}", macro_button_index + 1u).c_str())); if (!bindings.empty()) { - AddBindings(bindings, InputButtonEventHandler{[pad_index, macro_button_index](bool state) { + const float deadzone = + si.GetFloatValue(section.c_str(), fmt::format("Macro{}Deadzone", macro_button_index + 1).c_str(), 0.0f); + AddBindings(bindings, InputAxisEventHandler{[pad_index, macro_button_index, deadzone](float value) { if (!System::IsValid()) return; + const bool state = (value > deadzone); SetMacroButtonState(pad_index, macro_button_index, state); }}); } @@ -1417,6 +1421,7 @@ void InputManager::CopyConfiguration(SettingsInterface* dest_si, const SettingsI { dest_si->CopyStringListValue(src_si, section.c_str(), TinyString::from_format("Macro{}", i + 1)); dest_si->CopyStringValue(src_si, section.c_str(), TinyString::from_format("Macro{}Binds", i + 1)); + dest_si->CopyFloatValue(src_si, section.c_str(), TinyString::from_format("Macro{}Pressure", i + 1)); dest_si->CopyUIntValue(src_si, section.c_str(), TinyString::from_format("Macro{}Frequency", i + 1)); dest_si->CopyBoolValue(src_si, section.c_str(), TinyString::from_format("Macro{}Toggle", i + 1)); } @@ -1685,6 +1690,10 @@ void InputManager::LoadMacroButtonConfig(const SettingsInterface& si, const std: const u32 frequency = std::min(si.GetUIntValue(section.c_str(), TinyString::from_format("Macro{}Frequency", i + 1u), 0u), std::numeric_limits::max()); + const u8 pressure = static_cast( + std::clamp(si.GetFloatValue(section.c_str(), TinyString::from_format("Macro{}Pressure", i + 1u), 1.0f), 0.0f, + 1.0f) * + 255.0f); const bool toggle = si.GetBoolValue(section.c_str(), TinyString::from_format("Macro{}Toggle", i + 1u), false); // convert binds @@ -1714,9 +1723,11 @@ void InputManager::LoadMacroButtonConfig(const SettingsInterface& si, const std: if (bind_indices.empty()) continue; - s_macro_buttons[pad][i].buttons = std::move(bind_indices); - s_macro_buttons[pad][i].toggle_frequency = static_cast(frequency); - s_macro_buttons[pad][i].trigger_toggle = toggle; + MacroButton& macro = s_macro_buttons[pad][i]; + macro.buttons = std::move(bind_indices); + macro.toggle_frequency = static_cast(frequency); + macro.trigger_toggle = toggle; + macro.trigger_pressure = pressure; } } @@ -1748,7 +1759,7 @@ void InputManager::ApplyMacroButton(u32 pad, const MacroButton& mb) if (!controller) return; - const float value = mb.toggle_state ? 1.0f : 0.0f; + const float value = static_cast(mb.toggle_state ? mb.trigger_pressure : 0) * (1.0f / 255.0f); for (const u32 btn : mb.buttons) controller->SetBindState(btn, value); }