InputManager: Add push to toggle for macros

Backport of f0a4ceb909
This commit is contained in:
Stenzek 2024-05-15 22:32:55 +10:00 committed by Connor McLaughlin
parent 12a0644315
commit 25bc75a468
5 changed files with 71 additions and 50 deletions

View File

@ -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<std::string_view> 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); });

View File

@ -10,7 +10,7 @@
<height>433</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,0">
<property name="leftMargin">
<number>0</number>
</property>
@ -104,17 +104,28 @@
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Select the trigger to activate this macro. This can be a single button, or combination of buttons (chord). Shift-click for multiple triggers.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_5" stretch="1,0">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Select the trigger to activate this macro. This can be a single button, or combination of buttons (chord). Shift-click for multiple triggers.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="triggerToggle">
<property name="text">
<string>Press To Toggle</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="InputBindingWidget" name="trigger">
@ -219,19 +230,6 @@
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>

View File

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

View File

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

View File

@ -30,10 +30,11 @@ namespace Pad
{
std::vector<u32> 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<u32>(si.GetUIntValue(section.c_str(),
TinyString::from_format("Macro{}Frequency", i + 1), 0u),
std::numeric_limits<u16>::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<u32> 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<u16>(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);
}
}