Pad: Move multitap into its own config section

And more config cleanups.
This commit is contained in:
Stenzek 2023-07-29 13:42:45 +10:00 committed by Connor McLaughlin
parent 50b66f526b
commit 8b0c101768
12 changed files with 221 additions and 143 deletions

View File

@ -52,8 +52,8 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett
populateControllerTypes();
onTypeChanged();
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(
m_dialog->getProfileSettingsInterface(), m_ui.controllerType, m_config_section, "Type", Pad::GetDefaultPadType(port));
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(m_dialog->getProfileSettingsInterface(),
m_ui.controllerType, m_config_section, "Type", Pad::GetControllerInfo(Pad::GetDefaultPadType(port))->name);
connect(m_ui.controllerType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ControllerBindingWidget::onTypeChanged);
connect(m_ui.bindings, &QPushButton::clicked, this, &ControllerBindingWidget::onBindingsClicked);
@ -79,7 +79,15 @@ void ControllerBindingWidget::populateControllerTypes()
void ControllerBindingWidget::onTypeChanged()
{
const bool is_initializing = (m_ui.stackedWidget->count() == 0);
m_controller_type = m_dialog->getStringValue(m_config_section.c_str(), "Type", Pad::GetDefaultPadType(m_port_number));
const std::string type_name = m_dialog->getStringValue(
m_config_section.c_str(), "Type", Pad::GetControllerInfo(Pad::GetDefaultPadType(m_port_number))->name);
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfoByName(type_name);
if (!cinfo)
{
Console.Error(fmt::format("Invalid controller type name '{}' in config, ignoring.", type_name));
cinfo = Pad::GetControllerInfo(Pad::ControllerType::NotConnected);
}
m_controller_type = cinfo->type;
if (m_bindings_widget)
{
@ -100,17 +108,16 @@ void ControllerBindingWidget::onTypeChanged()
m_macros_widget = nullptr;
}
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_controller_type);
const bool has_settings = (cinfo && !cinfo->settings.empty());
const bool has_macros = (cinfo && !cinfo->bindings.empty());
const bool has_settings = (!cinfo->settings.empty());
const bool has_macros = (!cinfo->bindings.empty());
m_ui.settings->setEnabled(has_settings);
m_ui.macros->setEnabled(has_macros);
if (m_controller_type == "DualShock2")
if (cinfo->type == Pad::ControllerType::DualShock2)
{
m_bindings_widget = ControllerBindingWidget_DualShock2::createInstance(this);
}
else if (m_controller_type == "Guitar")
else if (cinfo->type == Pad::ControllerType::Guitar)
{
m_bindings_widget = ControllerBindingWidget_Guitar::createInstance(this);
}

View File

@ -49,7 +49,7 @@ public:
__fi ControllerSettingsDialog* getDialog() const { return m_dialog; }
__fi const std::string& getConfigSection() const { return m_config_section; }
__fi const std::string& getControllerType() const { return m_controller_type; }
__fi Pad::ControllerType getControllerType() const { return m_controller_type; }
__fi u32 getPortNumber() const { return m_port_number; }
private Q_SLOTS:
@ -70,7 +70,7 @@ private:
ControllerSettingsDialog* m_dialog;
std::string m_config_section;
std::string m_controller_type;
Pad::ControllerType m_controller_type;
u32 m_port_number;
ControllerBindingWidget_Base* m_bindings_widget = nullptr;
@ -170,7 +170,7 @@ public:
__fi ControllerSettingsDialog* getDialog() const { return static_cast<ControllerBindingWidget*>(parent())->getDialog(); }
__fi const std::string& getConfigSection() const { return static_cast<ControllerBindingWidget*>(parent())->getConfigSection(); }
__fi const std::string& getControllerType() const { return static_cast<ControllerBindingWidget*>(parent())->getControllerType(); }
__fi Pad::ControllerType getControllerType() const { return static_cast<ControllerBindingWidget*>(parent())->getControllerType(); }
__fi u32 getPortNumber() const { return static_cast<ControllerBindingWidget*>(parent())->getPortNumber(); }
virtual QIcon getIcon() const;

View File

@ -417,7 +417,7 @@ void SetupWizardDialog::setupControllerPage()
for (const auto& [name, display_name] : Pad::GetControllerTypeNames())
w.type_combo->addItem(QString::fromUtf8(display_name), QString::fromUtf8(name));
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(
nullptr, w.type_combo, section, "Type", Pad::GetDefaultPadType(port));
nullptr, w.type_combo, section, "Type", Pad::GetControllerInfo(Pad::GetDefaultPadType(port))->name);
w.mapping_result->setText((port == 0) ? tr("Default (Keyboard)") : tr("Default (None)"));

View File

@ -27,6 +27,11 @@ class SettingsWrapper;
enum class CDVD_SourceType : uint8_t;
namespace Pad
{
enum class ControllerType : u8;
}
/// Generic setting information which can be reused in multiple components.
struct SettingInfo
{
@ -1196,6 +1201,39 @@ struct Pcsx2Config
bool operator!=(const USBOptions& right) const;
};
// ------------------------------------------------------------------------
struct PadOptions
{
static constexpr u32 NUM_PORTS = 8;
struct Port
{
Pad::ControllerType Type;
bool operator==(const PadOptions::Port& right) const;
bool operator!=(const PadOptions::Port& right) const;
};
std::array<Port, NUM_PORTS> Ports;
BITFIELD32()
bool
MultitapPort0_Enabled : 1,
MultitapPort1_Enabled;
BITFIELD_END
PadOptions();
void LoadSave(SettingsWrapper& wrap);
bool IsMultitapPortEnabled(u32 port) const
{
return (port == 0) ? MultitapPort0_Enabled : MultitapPort1_Enabled;
}
bool operator==(const PadOptions& right) const;
bool operator!=(const PadOptions& right) const;
};
// ------------------------------------------------------------------------
// Options struct for each memory card.
//
@ -1266,10 +1304,6 @@ struct Pcsx2Config
McdEnableEjection : 1,
McdFolderAutoManage : 1,
MultitapPort0_Enabled : 1,
MultitapPort1_Enabled : 1,
ConsoleToStdio : 1,
HostFs : 1,
WarnAboutUnsafeSettings : 1;
@ -1290,6 +1324,7 @@ struct Pcsx2Config
SPU2Options SPU2;
DEV9Options DEV9;
USBOptions USB;
PadOptions Pad;
TraceLogFilters Trace;
@ -1323,8 +1358,6 @@ struct Pcsx2Config
std::string FullpathToBios() const;
std::string FullpathToMcd(uint slot) const;
bool MultitapEnabled(uint port) const;
bool operator==(const Pcsx2Config& right) const;
bool operator!=(const Pcsx2Config& right) const
{

View File

@ -3854,17 +3854,14 @@ void FullscreenUI::DrawControllerSettingsPage()
.c_str());
const char* section = sections[global_slot];
const std::string type(bsi->GetStringValue(section, "Type", Pad::GetDefaultPadType(global_slot)));
const Pad::ControllerInfo* ci = Pad::GetControllerInfo(type);
const Pad::ControllerInfo* ci = Pad::GetConfigControllerType(*bsi, section, global_slot);
if (MenuButton(ICON_FA_GAMEPAD " Controller Type", ci ? ci->display_name : "Unknown"))
{
const std::vector<std::pair<const char*, const char*>> raw_options = Pad::GetControllerTypeNames();
ImGuiFullscreen::ChoiceDialogOptions options;
options.reserve(raw_options.size());
for (auto& it : raw_options)
{
options.emplace_back(it.second, type == it.first);
}
options.emplace_back(it.second, (ci && ci->name == it.first));
OpenChoiceDialog(fmt::format("Port {} Controller Type", global_slot + 1).c_str(), false, std::move(options),
[game_settings = IsEditingGameSettings(bsi), section, raw_options = std::move(raw_options)](
s32 index, const std::string& title, bool checked) {

View File

@ -111,7 +111,7 @@ namespace InputManager
static float ApplySingleBindingScale(float sensitivity, float deadzone, float value);
static void AddHotkeyBindings(SettingsInterface& si);
static void AddPadBindings(SettingsInterface& si, u32 pad, const char* default_type);
static void AddPadBindings(SettingsInterface& si, u32 pad);
static void AddUSBBindings(SettingsInterface& si, u32 port);
static void UpdateContinuedVibration();
static void GenerateRelativeMouseEvents();
@ -625,16 +625,18 @@ void InputManager::AddHotkeyBindings(SettingsInterface& si)
}
}
void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index, const char* default_type)
void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index)
{
const std::string section(fmt::format("Pad{}", pad_index + 1));
const std::string type(si.GetStringValue(section.c_str(), "Type", default_type));
if (type.empty() || type == "None")
const Pad::ControllerType type = EmuConfig.Pad.Ports[pad_index].Type;
if (type == Pad::ControllerType::NotConnected)
{
// Don't bother checking macros/vibration if it's not a connected type.
return;
}
const std::string section = Pad::GetConfigSection(pad_index);
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(type);
if (!cinfo)
return;
pxAssert(cinfo);
for (const InputBindingInfo& bi : cinfo->bindings)
{
@ -1291,7 +1293,7 @@ void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& bind
// If there's an input profile, we load pad bindings from it alone, rather than
// falling back to the base configuration.
for (u32 pad = 0; pad < Pad::NUM_CONTROLLER_PORTS; pad++)
AddPadBindings(binding_si, pad, Pad::GetDefaultPadType(pad));
AddPadBindings(binding_si, pad);
constexpr float ui_ctrl_range = 100.0f;
constexpr float pointer_sensitivity = 0.05f;

View File

@ -24,6 +24,7 @@
#include "GS.h"
#include "CDVD/CDVDcommon.h"
#include "SIO/Memcard/MemoryCardFile.h"
#include "SIO/Pad/Pad.h"
#include "USB/USB.h"
#ifdef _WIN32
@ -1347,6 +1348,74 @@ bool Pcsx2Config::USBOptions::operator!=(const USBOptions& right) const
return !this->operator==(right);
}
Pcsx2Config::PadOptions::PadOptions()
{
for (u32 i = 0; i < static_cast<u32>(Ports.size()); i++)
{
Port& port = Ports[i];
port.Type = Pad::GetDefaultPadType(i);
}
bitset = 0;
}
void Pcsx2Config::PadOptions::LoadSave(SettingsWrapper& wrap)
{
for (u32 i = 0; i < static_cast<u32>(Ports.size()); i++)
{
Port& port = Ports[i];
std::string section = Pad::GetConfigSection(i);
std::string type_name = Pad::GetControllerInfo(port.Type)->name;
wrap.Entry(section.c_str(), "Type", type_name, type_name);
if (wrap.IsLoading())
{
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfoByName(type_name);
if (cinfo)
{
port.Type = cinfo->type;
}
else
{
Console.Error(fmt::format("Invalid controller type {} specified in config, disconnecting.", type_name));
port.Type = Pad::ControllerType::NotConnected;
}
}
}
SettingsWrapSection("Pad");
SettingsWrapBitBoolEx(MultitapPort0_Enabled, "MultitapPort1");
SettingsWrapBitBoolEx(MultitapPort1_Enabled, "MultitapPort2");
}
bool Pcsx2Config::PadOptions::operator==(const PadOptions& right) const
{
for (u32 i = 0; i < static_cast<u32>(Ports.size()); i++)
{
if (!OpEqu(Ports[i]))
return false;
}
return true;
}
bool Pcsx2Config::PadOptions::operator!=(const PadOptions& right) const
{
return !this->operator==(right);
}
bool Pcsx2Config::PadOptions::Port::operator==(const PadOptions::Port& right) const
{
return OpEqu(Type);
}
bool Pcsx2Config::PadOptions::Port::operator!=(const PadOptions::Port& right) const
{
return !this->operator==(right);
}
#ifdef ENABLE_ACHIEVEMENTS
Pcsx2Config::AchievementsOptions::AchievementsOptions()
@ -1438,7 +1507,6 @@ void Pcsx2Config::LoadSave(SettingsWrapper& wrap)
SettingsWrapBitBool(SaveStateOnShutdown);
SettingsWrapBitBool(EnableDiscordPresence);
SettingsWrapBitBool(InhibitScreensaver);
SettingsWrapBitBool(ConsoleToStdio);
SettingsWrapBitBool(HostFs);
SettingsWrapBitBool(BackupSavestate);
@ -1461,6 +1529,7 @@ void Pcsx2Config::LoadSave(SettingsWrapper& wrap)
Debugger.LoadSave(wrap);
Trace.LoadSave(wrap);
USB.LoadSave(wrap);
Pad.LoadSave(wrap);
#ifdef ENABLE_ACHIEVEMENTS
Achievements.LoadSave(wrap);
@ -1510,12 +1579,6 @@ void Pcsx2Config::LoadSaveMemcards(SettingsWrapper& wrap)
}
}
bool Pcsx2Config::MultitapEnabled(uint port) const
{
pxAssert(port < 2);
return (port == 0) ? MultitapPort0_Enabled : MultitapPort1_Enabled;
}
std::string Pcsx2Config::FullpathToBios() const
{
std::string ret;

View File

@ -272,9 +272,9 @@ void FileMemoryCard::Open()
if (FileMcd_IsMultitapSlot(slot))
{
if (!EmuConfig.MultitapPort0_Enabled && (FileMcd_GetMtapPort(slot) == 0))
if (!EmuConfig.Pad.MultitapPort0_Enabled && (FileMcd_GetMtapPort(slot) == 0))
continue;
if (!EmuConfig.MultitapPort1_Enabled && (FileMcd_GetMtapPort(slot) == 1))
if (!EmuConfig.Pad.MultitapPort1_Enabled && (FileMcd_GetMtapPort(slot) == 1))
continue;
}

View File

@ -25,6 +25,7 @@
#include "IconsFontAwesome5.h"
#include "common/Assertions.h"
#include "common/FileSystem.h"
#include "common/Path.h"
#include "common/SettingsInterface.h"
@ -46,11 +47,13 @@ namespace Pad
bool trigger_state; ///< Whether the macro button is active.
};
static const char* GetControllerTypeName(Pad::ControllerType type);
static std::unique_ptr<PadBase> CreatePad(u8 unifiedSlot, Pad::ControllerType controllerType);
static PadBase* ChangePadType(u8 unifiedSlot, Pad::ControllerType controllerType);
void LoadMacroButtonConfig(
const SettingsInterface& si, u32 pad, const std::string_view& type, const std::string& section);
const SettingsInterface& si, u32 pad, const ControllerInfo* ci, const std::string& section);
static void ApplyMacroButton(u32 controller, const MacroButton& mb);
static std::array<std::array<MacroButton, NUM_MACRO_BUTTONS_PER_CONTROLLER>, NUM_CONTROLLER_PORTS> s_macro_buttons;
@ -73,40 +76,35 @@ const char* Pad::ControllerInfo::GetLocalizedName() const
return Host::TranslateToCString("Pad", display_name);
}
std::optional<u32> Pad::ControllerInfo::GetBindIndex(const std::string_view& name) const
{
for (u32 i = 0; i < static_cast<u32>(bindings.size()); i++)
{
if (name == bindings[i].name)
return i;
}
return std::nullopt;
}
void Pad::LoadConfig(const SettingsInterface& si)
{
s_macro_buttons = {};
EmuConfig.MultitapPort0_Enabled = si.GetBoolValue("Pad", "MultitapPort1", false);
EmuConfig.MultitapPort1_Enabled = si.GetBoolValue("Pad", "MultitapPort2", false);
// This is where we would load controller types, if onepad supported them.
for (u32 i = 0; i < Pad::NUM_CONTROLLER_PORTS; i++)
{
const std::string section(GetConfigSection(i));
const std::string type(si.GetStringValue(section.c_str(), "Type", GetDefaultPadType(i)));
const ControllerInfo* ci = GetControllerInfo(type);
PadBase* pad = Pad::GetPad(i);
const std::string section = GetConfigSection(i);
const ControllerInfo* ci = GetControllerInfo(EmuConfig.Pad.Ports[i].Type);
pxAssert(ci);
// If a pad is not yet constructed, at minimum place a NotConnected pad in the slot.
// Do not abort the for loop - If there pad settings, we want those to be applied to the slot.
if (!pad)
{
pad = Pad::ChangePadType(i, Pad::ControllerType::NotConnected);
}
if (!ci)
{
pad = Pad::ChangePadType(i, Pad::ControllerType::NotConnected);
continue;
}
const Pad::ControllerType oldType = pad->GetType();
if (ci->type != oldType)
PadBase* pad = Pad::GetPad(i);
if (!pad || pad->GetType() != ci->type)
{
pad = Pad::ChangePadType(i, ci->type);
pxAssert(pad);
}
const float axis_deadzone = si.GetFloatValue(section.c_str(), "Deadzone", Pad::DEFAULT_STICK_DEADZONE);
@ -133,13 +131,13 @@ void Pad::LoadConfig(const SettingsInterface& si)
const int invert_r = si.GetIntValue(section.c_str(), "InvertR", 0);
pad->SetAnalogInvertL((invert_l & 1) != 0, (invert_l & 2) != 0);
pad->SetAnalogInvertR((invert_r & 1) != 0, (invert_r & 2) != 0);
LoadMacroButtonConfig(si, i, type, section);
LoadMacroButtonConfig(si, i, ci, section);
}
}
const char* Pad::GetDefaultPadType(u32 pad)
Pad::ControllerType Pad::GetDefaultPadType(u32 pad)
{
return (pad == 0) ? "DualShock2" : "None";
return (pad == 0) ? ControllerType::DualShock2 : ControllerType::NotConnected;
}
void Pad::SetDefaultControllerConfig(SettingsInterface& si)
@ -166,36 +164,32 @@ void Pad::SetDefaultControllerConfig(SettingsInterface& si)
// PCSX2 Controller Settings - Default pad types and parameters.
for (u32 i = 0; i < Pad::NUM_CONTROLLER_PORTS; i++)
{
const char* type = GetDefaultPadType(i);
const std::string section(GetConfigSection(i));
const std::string section = GetConfigSection(i);
const ControllerInfo* ci = GetControllerInfo(GetDefaultPadType(i));
si.ClearSection(section.c_str());
si.SetStringValue(section.c_str(), "Type", type);
si.SetStringValue(section.c_str(), "Type", ci->name);
const ControllerInfo* ci = GetControllerInfo(type);
if (ci)
for (const SettingInfo& csi : ci->settings)
{
for (const SettingInfo& csi : ci->settings)
switch (csi.type)
{
switch (csi.type)
{
case SettingInfo::Type::Boolean:
si.SetBoolValue(section.c_str(), csi.name, csi.BooleanDefaultValue());
break;
case SettingInfo::Type::Integer:
case SettingInfo::Type::IntegerList:
si.SetIntValue(section.c_str(), csi.name, csi.IntegerDefaultValue());
break;
case SettingInfo::Type::Float:
si.SetFloatValue(section.c_str(), csi.name, csi.FloatDefaultValue());
break;
case SettingInfo::Type::String:
case SettingInfo::Type::StringList:
case SettingInfo::Type::Path:
si.SetStringValue(section.c_str(), csi.name, csi.StringDefaultValue());
break;
default:
break;
}
case SettingInfo::Type::Boolean:
si.SetBoolValue(section.c_str(), csi.name, csi.BooleanDefaultValue());
break;
case SettingInfo::Type::Integer:
case SettingInfo::Type::IntegerList:
si.SetIntValue(section.c_str(), csi.name, csi.IntegerDefaultValue());
break;
case SettingInfo::Type::Float:
si.SetFloatValue(section.c_str(), csi.name, csi.FloatDefaultValue());
break;
case SettingInfo::Type::String:
case SettingInfo::Type::StringList:
case SettingInfo::Type::Path:
si.SetStringValue(section.c_str(), csi.name, csi.StringDefaultValue());
break;
default:
break;
}
}
}
@ -269,7 +263,7 @@ const Pad::ControllerInfo* Pad::GetControllerInfo(Pad::ControllerType type)
return nullptr;
}
const Pad::ControllerInfo* Pad::GetControllerInfo(const std::string_view& name)
const Pad::ControllerInfo* Pad::GetControllerInfoByName(const std::string_view& name)
{
for (const ControllerInfo* info : s_controller_info)
{
@ -296,31 +290,17 @@ const std::vector<std::pair<const char*, const char*>> Pad::GetControllerTypeNam
return ret;
}
std::vector<std::string> Pad::GetControllerBinds(const std::string_view& type)
const Pad::ControllerInfo* Pad::GetConfigControllerType(const SettingsInterface& si, const char* section, u32 port)
{
std::vector<std::string> ret;
const ControllerInfo* info = GetControllerInfo(type);
if (info)
{
for (const InputBindingInfo& bi : info->bindings)
{
if (bi.bind_type == InputBindingInfo::Type::Unknown || bi.bind_type == InputBindingInfo::Type::Motor)
continue;
ret.emplace_back(bi.name);
}
}
return ret;
return GetControllerInfoByName(
si.GetStringValue(section, "Type", GetControllerInfo(GetDefaultPadType(port))->name).c_str());
}
void Pad::ClearPortBindings(SettingsInterface& si, u32 port)
{
const std::string section(StringUtil::StdStringFromFormat("Pad%u", port + 1));
const std::string type(si.GetStringValue(section.c_str(), "Type", GetDefaultPadType(port)));
const ControllerInfo* info = GetControllerInfo(type);
// Why don't these just access EmuConfig? Input Profiles.
const std::string section = GetConfigSection(port);
const ControllerInfo* info = GetConfigControllerType(si, section.c_str(), port);
if (!info)
return;
@ -351,14 +331,13 @@ void Pad::CopyConfiguration(SettingsInterface* dest_si, const SettingsInterface&
for (u32 port = 0; port < Pad::NUM_CONTROLLER_PORTS; port++)
{
const std::string section(fmt::format("Pad{}", port + 1));
const std::string type(src_si.GetStringValue(section.c_str(), "Type", GetDefaultPadType(port)));
const std::string section = GetConfigSection(port);
if (copy_pad_config)
dest_si->SetStringValue(section.c_str(), "Type", type.c_str());
dest_si->CopyStringValue(src_si, section.c_str(), "Type");
const ControllerInfo* info = GetControllerInfo(type);
const Pad::ControllerInfo* info = GetConfigControllerType(src_si, section.c_str(), port);
if (!info)
return;
continue;
if (copy_pad_bindings)
{
@ -451,9 +430,8 @@ static u32 TryMapGenericMapping(SettingsInterface& si, const std::string& sectio
bool Pad::MapController(SettingsInterface& si, u32 controller,
const std::vector<std::pair<GenericInputBinding, std::string>>& mapping)
{
const std::string section(StringUtil::StdStringFromFormat("Pad%u", controller + 1));
const std::string type(si.GetStringValue(section.c_str(), "Type", GetDefaultPadType(controller)));
const ControllerInfo* info = GetControllerInfo(type);
const std::string section = GetConfigSection(controller);
const ControllerInfo* info = GetConfigControllerType(si, section.c_str(), controller);
if (!info)
return false;
@ -571,8 +549,8 @@ bool Pad::Freeze(StateWrapper& sw)
"Controller port {}, slot {} has a {} connected, but the save state has a "
"{}.\nLeaving the original controller type connected, but this may cause issues."),
port, slot,
Pad::GetControllerTypeName(pad ? pad->GetType() : Pad::ControllerType::NotConnected),
Pad::GetControllerTypeName(type)));
GetControllerTypeName(pad ? pad->GetType() : Pad::ControllerType::NotConnected),
GetControllerTypeName(type)));
// Reset the transfer etc state of the pad, at least it has a better chance of surviving.
if (pad)
@ -606,11 +584,8 @@ bool Pad::Freeze(StateWrapper& sw)
}
void Pad::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const std::string_view& type, const std::string& section)
void Pad::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const ControllerInfo* ci, const std::string& section)
{
// lazily initialized
std::vector<std::string> binds;
for (u32 i = 0; i < NUM_MACRO_BUTTONS_PER_CONTROLLER; i++)
{
std::string binds_string;
@ -618,9 +593,6 @@ void Pad::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const std:
continue;
const u32 frequency = si.GetUIntValue(section.c_str(), StringUtil::StdStringFromFormat("Macro%uFrequency", i + 1).c_str(), 0u);
if (binds.empty())
binds = GetControllerBinds(type);
const float pressure = si.GetFloatValue(section.c_str(), fmt::format("Macro{}Pressure", i + 1).c_str(), 1.0f);
// convert binds
@ -630,14 +602,14 @@ void Pad::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const std:
continue;
for (const std::string_view& button : buttons_split)
{
auto it = std::find(binds.begin(), binds.end(), button);
if (it == binds.end())
std::optional<u32> bind_index = ci->GetBindIndex(button);
if (!bind_index.has_value())
{
Console.Error("Invalid bind '%.*s' in macro button %u for pad %u", static_cast<int>(button.size()), button.data(), pad, i);
Console.Error(fmt::format("Invalid bind '{}' in macro button {} for pad {}", button, i, pad));
continue;
}
bind_indices.push_back(static_cast<u32>(std::distance(binds.begin(), it)));
bind_indices.push_back(bind_index.value());
}
if (bind_indices.empty())
continue;

View File

@ -32,7 +32,7 @@ namespace Pad
void Shutdown();
// Returns the default type for the specified port.
const char* GetDefaultPadType(u32 pad);
Pad::ControllerType GetDefaultPadType(u32 pad);
// Reloads configuration.
void LoadConfig(const SettingsInterface& si);
@ -51,13 +51,13 @@ namespace Pad
// Returns a list of controller type names. Pair of [name, display name].
const std::vector<std::pair<const char*, const char*>> GetControllerTypeNames();
// Returns the list of binds for the specified controller type.
std::vector<std::string> GetControllerBinds(const std::string_view& type);
// Returns general information for the specified controller type.
const ControllerInfo* GetControllerInfo(Pad::ControllerType type);
const ControllerInfo* GetControllerInfo(const std::string_view& name);
const char* GetControllerTypeName(Pad::ControllerType type);
const ControllerInfo* GetControllerInfoByName(const std::string_view& name);
// Returns controller info based on the type in the config.
// Needed because we can't just read EmuConfig when altering input profiles.
const ControllerInfo* GetConfigControllerType(const SettingsInterface& si, const char* section, u32 port);
// Performs automatic controller mapping with the provided list of generic mappings.
bool MapController(

View File

@ -17,6 +17,7 @@
#include "Config.h"
#include <optional>
#include <span>
namespace Pad
@ -95,12 +96,15 @@ namespace Pad
std::span<const SettingInfo> settings;
VibrationCapabilities vibration_caps;
// Returns localized controller type name.
/// Returns localized controller type name.
const char* GetLocalizedName() const;
/// Returns the index of the specified binding point, by name.
std::optional<u32> GetBindIndex(const std::string_view& name) const;
};
// Total number of pad ports, across both multitaps.
static constexpr u32 NUM_CONTROLLER_PORTS = 8;
static constexpr u32 NUM_CONTROLLER_PORTS = Pcsx2Config::PadOptions::NUM_PORTS;
// Default stick deadzone/sensitivity.
static constexpr float DEFAULT_STICK_DEADZONE = 0.0f;

View File

@ -166,7 +166,7 @@ void Sio2::Multitap()
{
g_Sio2FifoOut.push_back(0x00);
const bool multitapEnabled = (port == 0 && EmuConfig.MultitapPort0_Enabled) || (port == 1 && EmuConfig.MultitapPort1_Enabled);
const bool multitapEnabled = EmuConfig.Pad.IsMultitapPortEnabled(port);
SetRecv1(multitapEnabled ? Recv1::CONNECTED : Recv1::DISCONNECTED);
if (multitapEnabled)