Controller: Refactor so that GetControllerInfo() can't return null

This commit is contained in:
Stenzek 2025-01-13 16:07:40 +10:00
parent 062776c1c7
commit 462a4a3b50
No known key found for this signature in database
12 changed files with 85 additions and 131 deletions

View File

@ -23,20 +23,21 @@
static const Controller::ControllerInfo s_none_info = {
ControllerType::None, "None", TRANSLATE_NOOP("ControllerType", "Not Connected"), ICON_PF_QUESTION, {}, {}};
static const Controller::ControllerInfo* s_controller_info[] = {
&s_none_info,
&DigitalController::INFO,
&AnalogController::INFO,
&AnalogJoystick::INFO,
&NeGcon::INFO,
&NeGconRumble::INFO,
&GunCon::INFO,
&PlayStationMouse::INFO,
&Justifier::INFO,
&DigitalController::INFO_POPN,
&DigitalController::INFO_DDGO,
&JogCon::INFO,
};
static constexpr std::array<const Controller::ControllerInfo*, static_cast<size_t>(ControllerType::Count)>
s_controller_info = {{
&s_none_info,
&DigitalController::INFO,
&AnalogController::INFO,
&AnalogJoystick::INFO,
&GunCon::INFO,
&PlayStationMouse::INFO,
&NeGcon::INFO,
&NeGconRumble::INFO,
&Justifier::INFO,
&DigitalController::INFO_POPN,
&DigitalController::INFO_DDGO,
&JogCon::INFO,
}};
const std::array<u32, NUM_CONTROLLER_AND_CARD_PORTS> Controller::PortDisplayOrder = {{0, 2, 3, 4, 1, 5, 6, 7}};
@ -147,21 +148,10 @@ std::unique_ptr<Controller> Controller::Create(ControllerType type, u32 index)
}
}
const char* Controller::GetDefaultPadType(u32 pad)
const Controller::ControllerInfo& Controller::GetControllerInfo(ControllerType type)
{
return GetControllerInfo((pad == 0) ? Settings::DEFAULT_CONTROLLER_1_TYPE : Settings::DEFAULT_CONTROLLER_2_TYPE)
->name;
}
const Controller::ControllerInfo* Controller::GetControllerInfo(ControllerType type)
{
for (const ControllerInfo* info : s_controller_info)
{
if (type == info->type)
return info;
}
return nullptr;
DebugAssert(type < ControllerType::Count && s_controller_info[static_cast<size_t>(type)]);
return *s_controller_info[static_cast<size_t>(type)];
}
const Controller::ControllerInfo* Controller::GetControllerInfo(std::string_view name)
@ -175,26 +165,12 @@ const Controller::ControllerInfo* Controller::GetControllerInfo(std::string_view
return nullptr;
}
std::span<const Controller::ControllerInfo*> Controller::GetControllerInfoList()
const std::array<const Controller::ControllerInfo*, static_cast<size_t>(ControllerType::Count)>&
Controller::GetControllerInfoList()
{
return s_controller_info;
}
std::optional<u32> Controller::GetBindIndex(ControllerType type, std::string_view bind_name)
{
const ControllerInfo* info = GetControllerInfo(type);
if (!info)
return std::nullopt;
for (u32 i = 0; i < static_cast<u32>(info->bindings.size()); i++)
{
if (bind_name == info->bindings[i].name)
return i;
}
return std::nullopt;
}
std::tuple<u32, u32> Controller::ConvertPadToPortAndSlot(u32 index)
{
if (index > 4) // [5,6,7]

View File

@ -93,17 +93,11 @@ public:
/// Creates a new controller of the specified type.
static std::unique_ptr<Controller> Create(ControllerType type, u32 index);
/// Returns the default type for the specified port.
static const char* GetDefaultPadType(u32 pad);
/// Returns a list of all controller types.
static std::span<const ControllerInfo*> GetControllerInfoList();
/// Gets the integer code for an axis in the specified controller type.
static std::optional<u32> GetBindIndex(ControllerType type, std::string_view bind_name);
static const std::array<const ControllerInfo*, static_cast<size_t>(ControllerType::Count)>& GetControllerInfoList();
/// Returns general information for the specified controller type.
static const ControllerInfo* GetControllerInfo(ControllerType type);
static const ControllerInfo& GetControllerInfo(ControllerType type);
static const ControllerInfo* GetControllerInfo(std::string_view name);
/// Applies an analog deadzone/sensitivity.

View File

@ -1350,15 +1350,11 @@ void FullscreenUI::DoToggleAnalogMode()
Host::RunOnCPUThread([]() {
for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
{
Controller* ctrl = System::GetController(i);
Controller* const ctrl = System::GetController(i);
if (!ctrl)
continue;
const Controller::ControllerInfo* cinfo = Controller::GetControllerInfo(ctrl->GetType());
if (!cinfo)
continue;
for (const Controller::ControllerBindingInfo& bi : cinfo->bindings)
for (const Controller::ControllerBindingInfo& bi : Controller::GetControllerInfo(ctrl->GetType()).bindings)
{
if (std::strcmp(bi.name, "Analog") == 0)
{
@ -4099,8 +4095,8 @@ void FullscreenUI::DrawControllerSettingsPage()
Controller::GetPortDisplayName(mtap_port, mtap_slot, mtap_enabled[mtap_port])));
const TinyString section = TinyString::from_format("Pad{}", global_slot + 1);
const TinyString type =
bsi->GetTinyStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(global_slot));
const TinyString type = bsi->GetTinyStringValue(
section.c_str(), "Type", Controller::GetControllerInfo(Settings::GetDefaultControllerType(global_slot)).name);
const Controller::ControllerInfo* ci = Controller::GetControllerInfo(type);
TinyString value;
if (ci && ci->icon_name)
@ -4114,7 +4110,7 @@ void FullscreenUI::DrawControllerSettingsPage()
TinyString::from_format("{}##type{}", FSUI_ICONSTR(ICON_FA_GAMEPAD, "Controller Type"), global_slot),
FSUI_CSTR("Selects the type of emulated controller for this port."), value))
{
const std::span<const Controller::ControllerInfo*> infos = Controller::GetControllerInfoList();
const auto& infos = Controller::GetControllerInfoList();
ImGuiFullscreen::ChoiceDialogOptions options;
options.reserve(infos.size());
for (const Controller::ControllerInfo* it : infos)

View File

@ -756,7 +756,7 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
if (!supported_controller_string.empty())
supported_controller_string.append(", ");
supported_controller_string.append(Controller::GetControllerInfo(supported_ctype)->GetDisplayName());
supported_controller_string.append(Controller::GetControllerInfo(supported_ctype).GetDisplayName());
}
Host::AddIconOSDWarning(
@ -765,7 +765,7 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
TRANSLATE_FS("GameDatabase",
"Controller in Port {0} ({1}) is not supported for this game.\nSupported controllers: "
"{2}\nPlease configure a supported controller from the list above."),
i + 1u, Controller::GetControllerInfo(ctype)->GetDisplayName(), supported_controller_string),
i + 1u, Controller::GetControllerInfo(ctype).GetDisplayName(), supported_controller_string),
Host::OSD_CRITICAL_ERROR_DURATION);
}
}
@ -857,7 +857,7 @@ std::string GameDatabase::Entry::GenerateCompatibilityReport() const
if ((supported_controllers & (static_cast<u16>(1) << j)) == 0)
continue;
ret.append_format(" - {}\n", Controller::GetControllerInfo(static_cast<ControllerType>(j))->GetDisplayName());
ret.append_format(" - {}\n", Controller::GetControllerInfo(static_cast<ControllerType>(j)).GetDisplayName());
}
if (supported_controllers & SUPPORTS_MULTITAP_BIT)

View File

@ -682,26 +682,22 @@ void ImGuiManager::DrawInputsOverlay()
for (const u32 pad : Controller::PortDisplayOrder)
{
if (g_settings.controller_types[pad] == ControllerType::None)
continue;
const Controller* controller = System::GetController(pad);
const Controller::ControllerInfo* cinfo =
controller ? Controller::GetControllerInfo(controller->GetType()) : nullptr;
if (!cinfo)
if (!controller)
continue;
const Controller::ControllerInfo& cinfo = Controller::GetControllerInfo(controller->GetType());
const auto& [port, slot] = Controller::ConvertPadToPortAndSlot(pad);
const char* port_label = Controller::GetPortDisplayName(port, slot, g_settings.IsMultitapPortEnabled(port));
float text_start_x = current_x;
if (cinfo->icon_name)
if (cinfo.icon_name)
{
const ImVec2 icon_size = font->CalcTextSizeA(font->FontSize, FLT_MAX, 0.0f, cinfo->icon_name);
const ImVec2 icon_size = font->CalcTextSizeA(font->FontSize, FLT_MAX, 0.0f, cinfo.icon_name);
const u32 icon_color = controller->GetInputOverlayIconColor();
dl->AddText(font, font->FontSize, ImVec2(current_x + shadow_offset, current_y + shadow_offset), shadow_color,
cinfo->icon_name, nullptr, 0.0f, &clip_rect);
dl->AddText(font, font->FontSize, ImVec2(current_x, current_y), icon_color, cinfo->icon_name, nullptr, 0.0f,
cinfo.icon_name, nullptr, 0.0f, &clip_rect);
dl->AddText(font, font->FontSize, ImVec2(current_x, current_y), icon_color, cinfo.icon_name, nullptr, 0.0f,
&clip_rect);
text_start_x += icon_size.x;
text.format(" {}", port_label);
@ -711,7 +707,7 @@ void ImGuiManager::DrawInputsOverlay()
text.format("{} |", port_label);
}
for (const Controller::ControllerBindingInfo& bi : cinfo->bindings)
for (const Controller::ControllerBindingInfo& bi : cinfo.bindings)
{
switch (bi.type)
{

View File

@ -208,19 +208,19 @@ bool Pad::DoStateController(StateWrapper& sw, u32 i)
if (controller_type != controller_type_in_state)
{
const Controller::ControllerInfo* state_cinfo = Controller::GetControllerInfo(controller_type_in_state);
const Controller::ControllerInfo& state_cinfo = Controller::GetControllerInfo(controller_type_in_state);
Assert(sw.IsReading());
DEV_LOG("Controller type mismatch in slot {}: state={}({}) ui={}({})", i + 1u, state_cinfo ? state_cinfo->name : "",
static_cast<unsigned>(controller_type_in_state), Controller::GetControllerInfo(controller_type)->name,
DEV_LOG("Controller type mismatch in slot {}: state={}({}) ui={}({})", i + 1u, state_cinfo.name,
static_cast<unsigned>(controller_type_in_state), Controller::GetControllerInfo(controller_type).name,
static_cast<unsigned>(controller_type));
Host::AddIconOSDWarning(
fmt::format("PadTypeMismatch{}", i), ICON_EMOJI_WARNING,
fmt::format(TRANSLATE_FS("OSDMessage",
"Save state contains controller type {0} in port {1}.\n Leaving {2} connected."),
state_cinfo ? state_cinfo->GetDisplayName() : "", i + 1u,
Controller::GetControllerInfo(controller_type)->GetDisplayName()),
state_cinfo.GetDisplayName(), i + 1u,
Controller::GetControllerInfo(controller_type).GetDisplayName()),
Host::OSD_WARNING_DURATION);
if (s_state.controllers[i])
@ -671,11 +671,11 @@ void Pad::WriteRegister(u32 offset, u32 value)
return;
}
[[unlikely]] default:
{
ERROR_LOG("Unknown register write: 0x{:X} <- 0x{:08X}", offset, value);
return;
}
[[unlikely]] default:
{
ERROR_LOG("Unknown register write: 0x{:X} <- 0x{:08X}", offset, value);
return;
}
}
}

View File

@ -405,7 +405,7 @@ void Settings::Load(const SettingsInterface& si, const SettingsInterface& contro
const ControllerType default_type = (pad == 0) ? DEFAULT_CONTROLLER_1_TYPE : DEFAULT_CONTROLLER_2_TYPE;
const Controller::ControllerInfo* cinfo = Controller::GetControllerInfo(controller_si.GetTinyStringValue(
Controller::GetSettingsSection(pad).c_str(), "Type", Controller::GetControllerInfo(default_type)->name));
Controller::GetSettingsSection(pad).c_str(), "Type", Controller::GetControllerInfo(default_type).name));
controller_types[pad] = cinfo ? cinfo->type : default_type;
}
@ -682,9 +682,8 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const
for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
{
const Controller::ControllerInfo* cinfo = Controller::GetControllerInfo(controller_types[i]);
DebugAssert(cinfo);
si.SetStringValue(Controller::GetSettingsSection(i).c_str(), "Type", cinfo->name);
si.SetStringValue(Controller::GetSettingsSection(i).c_str(), "Type",
Controller::GetControllerInfo(controller_types[i]).name);
}
si.SetStringValue("MemoryCards", "Card1Type", GetMemoryCardTypeName(memory_card_types[0]));
@ -1183,7 +1182,7 @@ void Settings::SetDefaultControllerConfig(SettingsInterface& si)
{
const std::string section(Controller::GetSettingsSection(i));
si.ClearSection(section.c_str());
si.SetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(i));
si.SetStringValue(section.c_str(), "Type", Controller::GetControllerInfo(GetDefaultControllerType(i)).name);
}
#ifndef __ANDROID__

View File

@ -389,6 +389,12 @@ struct Settings : public GPUSettings
return (port == 0) ? IsPort1MultitapEnabled() : IsPort2MultitapEnabled();
}
/// Returns the default type for the specified port.
ALWAYS_INLINE static ControllerType GetDefaultControllerType(u32 pad)
{
return (pad == 0) ? DEFAULT_CONTROLLER_1_TYPE : DEFAULT_CONTROLLER_2_TYPE;
}
ALWAYS_INLINE static bool IsPerGameMemoryCardType(MemoryCardType type)
{
return (type == MemoryCardType::PerGame || type == MemoryCardType::PerGameTitle ||

View File

@ -61,23 +61,14 @@ ControllerBindingWidget::~ControllerBindingWidget() = default;
void ControllerBindingWidget::populateControllerTypes()
{
for (u32 i = 0; i < static_cast<u32>(ControllerType::Count); i++)
{
const ControllerType ctype = static_cast<ControllerType>(i);
const Controller::ControllerInfo* cinfo = Controller::GetControllerInfo(ctype);
if (!cinfo)
continue;
m_ui.controllerType->addItem(QString::fromUtf8(cinfo->GetDisplayName()), QVariant(static_cast<int>(i)));
}
for (const Controller::ControllerInfo* cinfo : Controller::GetControllerInfoList())
m_ui.controllerType->addItem(QString::fromUtf8(cinfo->GetDisplayName()), QVariant(static_cast<int>(cinfo->type)));
m_controller_info = Controller::GetControllerInfo(
m_dialog->getStringValue(m_config_section.c_str(), "Type", Controller::GetDefaultPadType(m_port_number)));
m_dialog->getStringValue(m_config_section.c_str(), "Type",
Controller::GetControllerInfo(Settings::GetDefaultControllerType(m_port_number)).name));
if (!m_controller_info)
{
m_controller_info = Controller::GetControllerInfo(m_port_number == 0 ? Settings::DEFAULT_CONTROLLER_1_TYPE :
Settings::DEFAULT_CONTROLLER_2_TYPE);
}
m_controller_info = &Controller::GetControllerInfo(Settings::GetDefaultControllerType(m_port_number));
const int index = m_ui.controllerType->findData(QVariant(static_cast<int>(m_controller_info->type)));
if (index >= 0 && index != m_ui.controllerType->currentIndex())
@ -247,8 +238,7 @@ void ControllerBindingWidget::onTypeChanged()
if (!ok || index < 0 || index >= static_cast<int>(ControllerType::Count))
return;
m_controller_info = Controller::GetControllerInfo(static_cast<ControllerType>(index));
DebugAssert(m_controller_info);
m_controller_info = &Controller::GetControllerInfo(static_cast<ControllerType>(index));
SettingsInterface* sif = m_dialog->getEditingSettingsInterface();
if (sif)

View File

@ -195,7 +195,7 @@ void GameSummaryWidget::populateUi(const std::string& path, const std::string& s
{
if (!controllers.isEmpty())
controllers.append(", ");
controllers.append(Controller::GetControllerInfo(static_cast<ControllerType>(i))->GetDisplayName());
controllers.append(Controller::GetControllerInfo(static_cast<ControllerType>(i)).GetDisplayName());
}
}
}

View File

@ -404,18 +404,12 @@ void SetupWizardDialog::setupControllerPage(bool initial)
const std::string section = fmt::format("Pad{}", port + 1);
const PadWidgets& w = pad_widgets[port];
for (u32 i = 0; i < static_cast<u32>(ControllerType::Count); i++)
{
const ControllerType ctype = static_cast<ControllerType>(i);
const Controller::ControllerInfo* cinfo = Controller::GetControllerInfo(ctype);
if (!cinfo)
continue;
w.type_combo->addItem(qApp->translate("ControllerType", cinfo->display_name), QString::fromUtf8(cinfo->name));
}
for (const Controller::ControllerInfo* cinfo : Controller::GetControllerInfoList())
w.type_combo->addItem(QString::fromUtf8(cinfo->GetDisplayName()), QString::fromUtf8(cinfo->name));
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(
nullptr, w.type_combo, section, "Type", Controller::GetControllerInfo(Controller::GetDefaultPadType(port))->name);
nullptr, w.type_combo, section, "Type",
Controller::GetControllerInfo(Settings::GetDefaultControllerType(port)).name);
w.mapping_result->setText((port == 0) ? tr("Default (Keyboard)") : tr("Default (None)"));

View File

@ -120,7 +120,7 @@ static float ApplySingleBindingScale(float sensitivity, float deadzone, float va
static void AddHotkeyBindings(const SettingsInterface& si);
static void AddPadBindings(const SettingsInterface& si, const std::string& section, u32 pad,
const Controller::ControllerInfo* cinfo);
const Controller::ControllerInfo& cinfo);
static void UpdateContinuedVibration();
static void GenerateRelativeMouseEvents();
@ -129,7 +129,7 @@ static bool PreprocessEvent(InputBindingKey key, float value, GenericInputBindin
static bool ProcessEvent(InputBindingKey key, float value, bool skip_button_handlers);
static void LoadMacroButtonConfig(const SettingsInterface& si, const std::string& section, u32 pad,
const Controller::ControllerInfo* cinfo);
const Controller::ControllerInfo& cinfo);
static void ApplyMacroButton(u32 pad, const MacroButton& mb);
static void UpdateMacroButtons();
@ -834,13 +834,13 @@ void InputManager::AddHotkeyBindings(const SettingsInterface& si)
}
void InputManager::AddPadBindings(const SettingsInterface& si, const std::string& section, u32 pad_index,
const Controller::ControllerInfo* cinfo)
const Controller::ControllerInfo& cinfo)
{
bool vibration_binding_valid = false;
PadVibrationBinding vibration_binding = {};
vibration_binding.pad_index = pad_index;
for (const Controller::ControllerBindingInfo& bi : cinfo->bindings)
for (const Controller::ControllerBindingInfo& bi : cinfo.bindings)
{
const std::vector<std::string> bindings(si.GetStringList(section.c_str(), bi.name));
@ -1420,8 +1420,9 @@ void InputManager::SetDefaultSourceConfig(SettingsInterface& si)
void InputManager::ClearPortBindings(SettingsInterface& si, u32 port)
{
const std::string section(Controller::GetSettingsSection(port));
const std::string type(si.GetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(port)));
const std::string section = Controller::GetSettingsSection(port);
const TinyString type = si.GetTinyStringValue(
section.c_str(), "Type", Controller::GetControllerInfo(Settings::GetDefaultControllerType(port)).name);
const Controller::ControllerInfo* info = Controller::GetControllerInfo(type);
if (!info)
@ -1463,7 +1464,8 @@ void InputManager::CopyConfiguration(SettingsInterface* dest_si, const SettingsI
}
const std::string section(Controller::GetSettingsSection(port));
const std::string type(src_si.GetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(port)));
const TinyString type = src_si.GetTinyStringValue(
section.c_str(), "Type", Controller::GetControllerInfo(Settings::GetDefaultControllerType(port)).name);
if (copy_pad_config)
dest_si->SetStringValue(section.c_str(), "Type", type.c_str());
@ -1557,8 +1559,9 @@ static u32 TryMapGenericMapping(SettingsInterface& si, const std::string& sectio
bool InputManager::MapController(SettingsInterface& si, u32 controller,
const std::vector<std::pair<GenericInputBinding, std::string>>& mapping)
{
const std::string section(Controller::GetSettingsSection(controller));
const std::string type(si.GetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(controller)));
const std::string section = Controller::GetSettingsSection(controller);
const TinyString type = si.GetTinyStringValue(
section.c_str(), "Type", Controller::GetControllerInfo(Settings::GetDefaultControllerType(controller)).name);
const Controller::ControllerInfo* info = Controller::GetControllerInfo(type);
if (!info)
return false;
@ -1747,10 +1750,10 @@ void InputManager::UpdateContinuedVibration()
// ------------------------------------------------------------------------
void InputManager::LoadMacroButtonConfig(const SettingsInterface& si, const std::string& section, u32 pad,
const Controller::ControllerInfo* cinfo)
const Controller::ControllerInfo& cinfo)
{
s_macro_buttons[pad] = {};
if (cinfo->bindings.empty())
if (cinfo.bindings.empty())
return;
for (u32 i = 0; i < NUM_MACRO_BUTTONS_PER_CONTROLLER; i++)
@ -1776,7 +1779,7 @@ void InputManager::LoadMacroButtonConfig(const SettingsInterface& si, const std:
for (const std::string_view& button : buttons_split)
{
const Controller::ControllerBindingInfo* binding = nullptr;
for (const Controller::ControllerBindingInfo& bi : cinfo->bindings)
for (const Controller::ControllerBindingInfo& bi : cinfo.bindings)
{
if (button == bi.name)
{
@ -1918,10 +1921,10 @@ void InputManager::ReloadBindings(const SettingsInterface& binding_si, const Set
// falling back to the base configuration.
for (u32 pad = 0; pad < NUM_CONTROLLER_AND_CARD_PORTS; pad++)
{
const Controller::ControllerInfo* cinfo = Controller::GetControllerInfo(g_settings.controller_types[pad]);
if (!cinfo || cinfo->type == ControllerType::None)
if (g_settings.controller_types[pad] == ControllerType::None)
continue;
const Controller::ControllerInfo& cinfo = Controller::GetControllerInfo(g_settings.controller_types[pad]);
const std::string section(Controller::GetSettingsSection(pad));
AddPadBindings(binding_si, section, pad, cinfo);
LoadMacroButtonConfig(binding_si, section, pad, cinfo);