diff --git a/pcsx2-qt/Settings/ControllerBindingWidgets.cpp b/pcsx2-qt/Settings/ControllerBindingWidgets.cpp index 50638b0164..913c7351e6 100644 --- a/pcsx2-qt/Settings/ControllerBindingWidgets.cpp +++ b/pcsx2-qt/Settings/ControllerBindingWidgets.cpp @@ -326,7 +326,7 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare } // load binds (single string joined by &) - const std::string binds_string(dialog->getStringValue(section.c_str(), fmt::format("Macro{}Binds", index + 1u).c_str(), "")); + const std::string binds_string(dialog->getStringValue(section.c_str(), TinyString::from_format("Macro{}Binds", index + 1u), "")); const std::vector buttons_split(StringUtil::SplitString(binds_string, '&', true)); for (const std::string_view& button : buttons_split) @@ -367,6 +367,8 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare m_ui.trigger->initialize( dialog->getProfileSettingsInterface(), InputBindingInfo::Type::Macro, section, fmt::format("Macro{}", index + 1u)); + ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(dialog->getProfileSettingsInterface(), m_ui.triggerToggle, + section.c_str(), fmt::format("Macro{}Toggle", index + 1u), false); connect(m_ui.increaseFrequency, &QAbstractButton::clicked, this, [this]() { modFrequency(1); }); connect(m_ui.decreateFrequency, &QAbstractButton::clicked, this, [this]() { modFrequency(-1); }); diff --git a/pcsx2-qt/Settings/ControllerMacroEditWidget.ui b/pcsx2-qt/Settings/ControllerMacroEditWidget.ui index 044ae14fdc..5b51733f60 100644 --- a/pcsx2-qt/Settings/ControllerMacroEditWidget.ui +++ b/pcsx2-qt/Settings/ControllerMacroEditWidget.ui @@ -10,7 +10,7 @@ 433 - + 0 @@ -104,17 +104,28 @@ - - - Select the trigger to activate this macro. This can be a single button, or combination of buttons (chord). Shift-click for multiple triggers. - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - + + + + + Select the trigger to activate this macro. This can be a single button, or combination of buttons (chord). Shift-click for multiple triggers. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + Press To Toggle + + + + @@ -219,19 +230,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index 82a9de38de..88368a9b19 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -4378,8 +4378,10 @@ void FullscreenUI::DrawControllerSettingsPage() if (!expanded) continue; + ImGui::PushID(&expanded); + DrawInputBindingButton( - bsi, InputBindingInfo::Type::Macro, section, TinyString::from_format("Macro{}", macro_index + 1), "Trigger", nullptr); + bsi, InputBindingInfo::Type::Macro, section, TinyString::from_format("Macro{}", macro_index + 1), FSUI_CSTR("Trigger"), nullptr); SmallString binds_string = bsi->GetSmallStringValue(section, fmt::format("Macro{}Binds", macro_index + 1).c_str()); TinyString pretty_binds_string; @@ -4462,6 +4464,10 @@ 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, + TinyString::from_format("Macro{}Toggle", macro_index + 1), false, true, false); + const TinyString freq_key = TinyString::from_format("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, freq_key.c_str(), 0); @@ -4515,6 +4521,8 @@ void FullscreenUI::DrawControllerSettingsPage() ImGui::PopStyleVar(4); ImGui::PopFont(); + + ImGui::PopID(); } if (!ci->settings.empty()) @@ -7164,6 +7172,8 @@ TRANSLATE_NOOP("FullscreenUI", "The XInput source provides support for XBox 360/ TRANSLATE_NOOP("FullscreenUI", "Multitap"); TRANSLATE_NOOP("FullscreenUI", "Enables an additional three controller slots. Not supported in all games."); TRANSLATE_NOOP("FullscreenUI", "Attempts to map the selected port to a chosen controller."); +TRANSLATE_NOOP("FullscreenUI", "Trigger"); +TRANSLATE_NOOP("FullscreenUI", "Toggles the macro when the button is pressed, instead of held."); TRANSLATE_NOOP("FullscreenUI", "Determines the frequency at which the macro will toggle the buttons on and off (aka auto fire)."); TRANSLATE_NOOP("FullscreenUI", "Determines how much pressure is simulated when macro is active."); TRANSLATE_NOOP("FullscreenUI", "Determines the pressure required to activate the macro."); @@ -7606,6 +7616,7 @@ TRANSLATE_NOOP("FullscreenUI", "Controller Port {}{} Macros"); TRANSLATE_NOOP("FullscreenUI", "Controller Port {} Macros"); TRANSLATE_NOOP("FullscreenUI", "Macro Button {}"); TRANSLATE_NOOP("FullscreenUI", "Buttons"); +TRANSLATE_NOOP("FullscreenUI", "Press To Toggle"); TRANSLATE_NOOP("FullscreenUI", "Pressure"); TRANSLATE_NOOP("FullscreenUI", "Deadzone"); TRANSLATE_NOOP("FullscreenUI", "Controller Port {}{} Settings"); diff --git a/pcsx2/ImGui/ImGuiFullscreen.cpp b/pcsx2/ImGui/ImGuiFullscreen.cpp index 37fea51c4d..0293be2cf0 100644 --- a/pcsx2/ImGui/ImGuiFullscreen.cpp +++ b/pcsx2/ImGui/ImGuiFullscreen.cpp @@ -1328,7 +1328,7 @@ bool ImGuiFullscreen::ToggleButton( const float toggle_width = LayoutScale(50.0f); const float toggle_height = LayoutScale(25.0f); const float toggle_x = LayoutScale(8.0f); - const float toggle_y = (LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT) - toggle_height) * 0.5f; + const float toggle_y = (LayoutScale(height) - toggle_height) * 0.5f; const float toggle_radius = toggle_height * 0.5f; const ImVec2 toggle_pos(bb.Max.x - toggle_width - toggle_x, bb.Min.y + toggle_y); diff --git a/pcsx2/SIO/Pad/Pad.cpp b/pcsx2/SIO/Pad/Pad.cpp index e7d13cd5d2..4643ab5537 100644 --- a/pcsx2/SIO/Pad/Pad.cpp +++ b/pcsx2/SIO/Pad/Pad.cpp @@ -30,10 +30,11 @@ namespace Pad { std::vector buttons; ///< Buttons to activate. float pressure; ///< Pressure to apply when macro is active. - u32 toggle_frequency; ///< Interval at which the buttons will be toggled, if not 0. - u32 toggle_counter; ///< When this counter reaches zero, buttons will be toggled. + u16 toggle_frequency; ///< Interval at which the buttons will be toggled, if not 0. + u16 toggle_counter; ///< When this counter reaches zero, buttons will be toggled. 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. }; static const char* GetControllerTypeName(Pad::ControllerType type); @@ -49,7 +50,7 @@ namespace Pad bool mtapPort0LastState; bool mtapPort1LastState; -} +} // namespace Pad bool Pad::Initialize() { @@ -108,7 +109,7 @@ void Pad::LoadConfig(const SettingsInterface& si) // there was some kind of pad ejection event and properly detect the new one, and properly initiate its config sequence. pad = Pad::CreatePad(i, ci->type, (VMManager::GetState() != VMState::Shutdown ? Pad::DEFAULT_EJECT_TICKS : 0)); } - + pxAssert(pad); } @@ -142,7 +143,7 @@ void Pad::LoadConfig(const SettingsInterface& si) Pad::ControllerType Pad::GetDefaultPadType(u32 pad) { - return (pad == 0) ? ControllerType::DualShock2 : ControllerType::NotConnected; + return (pad == 0) ? ControllerType::DualShock2 : ControllerType::NotConnected; } void Pad::SetDefaultControllerConfig(SettingsInterface& si) @@ -350,11 +351,12 @@ void Pad::CopyConfiguration(SettingsInterface* dest_si, const SettingsInterface& for (u32 i = 0; i < NUM_MACRO_BUTTONS_PER_CONTROLLER; i++) { - dest_si->CopyStringListValue(src_si, section.c_str(), fmt::format("Macro{}", i + 1).c_str()); - dest_si->CopyFloatValue(src_si, section.c_str(), fmt::format("Macro{}Pressure", i + 1).c_str()); - dest_si->CopyFloatValue(src_si, section.c_str(), fmt::format("Macro{}Deadzone", i + 1).c_str()); - dest_si->CopyStringValue(src_si, section.c_str(), fmt::format("Macro{}Binds", i + 1).c_str()); - dest_si->CopyUIntValue(src_si, section.c_str(), fmt::format("Macro{}Frequency", i + 1).c_str()); + dest_si->CopyStringListValue(src_si, section.c_str(), TinyString::from_format("Macro{}", i + 1)); + dest_si->CopyFloatValue(src_si, section.c_str(), TinyString::from_format("Macro{}Pressure", i + 1)); + dest_si->CopyFloatValue(src_si, section.c_str(), TinyString::from_format("Macro{}Deadzone", i + 1)); + dest_si->CopyStringValue(src_si, section.c_str(), TinyString::from_format("Macro{}Binds", 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)); } } @@ -543,12 +545,12 @@ bool Pad::Freeze(StateWrapper& sw) { PadBase* currentPad = GetPad(unifiedSlot); ControllerType statePadType; - + sw.Do(&statePadType); - + if (sw.HasError()) return false; - + if (!currentPad) { pxAssertMsg(false, fmt::format("Pad::Freeze (on read) Existing Pad {0} was nullptr", unifiedSlot).c_str()); @@ -566,7 +568,7 @@ bool Pad::Freeze(StateWrapper& sw) port, slot, GetControllerTypeName(currentPad ? currentPad->GetType() : Pad::ControllerType::NotConnected), GetControllerTypeName(statePadType))); - + // Run the freeze, using a new pad instance of the old type just so we make sure all those attributes // from the state are read out and we aren't going to run into some sort of consistency problem. currentPad = CreatePad(unifiedSlot, statePadType); @@ -618,11 +620,14 @@ void Pad::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const Cont for (u32 i = 0; i < NUM_MACRO_BUTTONS_PER_CONTROLLER; i++) { std::string binds_string; - if (!si.GetStringValue(section.c_str(), StringUtil::StdStringFromFormat("Macro%uBinds", i + 1).c_str(), &binds_string)) + if (!si.GetStringValue(section.c_str(), TinyString::from_format("Macro{}Binds", i + 1), &binds_string)) continue; - const u32 frequency = si.GetUIntValue(section.c_str(), StringUtil::StdStringFromFormat("Macro%uFrequency", i + 1).c_str(), 0u); - const float pressure = si.GetFloatValue(section.c_str(), fmt::format("Macro{}Pressure", i + 1).c_str(), 1.0f); + const u32 frequency = std::min(si.GetUIntValue(section.c_str(), + TinyString::from_format("Macro{}Frequency", i + 1), 0u), + std::numeric_limits::max()); + const float pressure = si.GetFloatValue(section.c_str(), TinyString::from_format("Macro{}Pressure", i + 1), 1.0f); + const bool toggle = si.GetBoolValue(section.c_str(), TinyString::from_format("Macro{}Toggle", i + 1), false); // convert binds std::vector bind_indices; @@ -645,8 +650,9 @@ void Pad::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const Cont MacroButton& macro = s_macro_buttons[pad][i]; macro.buttons = std::move(bind_indices); - macro.toggle_frequency = frequency; + macro.toggle_frequency = static_cast(frequency); macro.pressure = pressure; + macro.trigger_toggle = toggle; } } @@ -656,14 +662,18 @@ void Pad::SetMacroButtonState(u32 pad, u32 index, bool state) return; MacroButton& mb = s_macro_buttons[pad][index]; - if (mb.buttons.empty() || mb.trigger_state == state) + if (mb.buttons.empty()) + return; + + const bool trigger_state = (mb.trigger_toggle ? (state ? !mb.trigger_state : mb.trigger_state) : state); + if (mb.trigger_state == trigger_state) return; mb.toggle_counter = mb.toggle_frequency; - mb.trigger_state = state; - if (mb.toggle_state != state) + mb.trigger_state = trigger_state; + if (mb.toggle_state != trigger_state) { - mb.toggle_state = state; + mb.toggle_state = trigger_state; ApplyMacroButton(pad, mb); } }