From 4e880280bde27bd0c659d7399baef3d98ecf34d0 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 27 Sep 2024 20:57:35 +1000 Subject: [PATCH] Qt: Fix inconsistent multitap addressing And remove multiple copies of the same variables while we're at it. --- src/core/controller.cpp | 11 +++++ src/core/controller.h | 20 ++++++--- src/core/fullscreen_ui.cpp | 45 ++++--------------- src/core/imgui_overlays.cpp | 13 +++--- src/core/multitap.cpp | 6 ++- src/core/settings.cpp | 14 +++--- src/core/settings.h | 2 +- .../controllersettingswindow.cpp | 19 +++----- src/duckstation-qt/controllersettingswindow.h | 9 +--- 9 files changed, 62 insertions(+), 77 deletions(-) diff --git a/src/core/controller.cpp b/src/core/controller.cpp index 571677cd7..1aee13852 100644 --- a/src/core/controller.cpp +++ b/src/core/controller.cpp @@ -32,6 +32,8 @@ static const Controller::ControllerInfo* s_controller_info[] = { &Justifier::INFO, }; +const std::array Controller::PortDisplayOrder = {{0, 2, 3, 4, 1, 5, 6, 7}}; + const char* Controller::ControllerInfo::GetDisplayName() const { return Host::TranslateToCString("ControllerType", display_name); @@ -211,6 +213,15 @@ bool Controller::PortAndSlotIsMultitap(u32 port, u32 slot) return (slot != 0); } +const char* Controller::GetPortDisplayName(u32 port, u32 slot, bool mtap) +{ + static constexpr const char* no_mtap_labels[] = {"1", "2"}; + static constexpr const char* mtap_labels[][4] = {{"1A", "1B", "1C", "1D"}, {"2A", "2B", "2C", "2D"}}; + + DebugAssert(port < 2 && slot < 4); + return mtap ? mtap_labels[port][slot] : no_mtap_labels[port]; +} + std::string Controller::GetSettingsSection(u32 pad) { return fmt::format("Pad{}", pad + 1u); diff --git a/src/core/controller.h b/src/core/controller.h index e8ce68333..da3d11537 100644 --- a/src/core/controller.h +++ b/src/core/controller.h @@ -111,6 +111,15 @@ public: static const ControllerInfo* GetControllerInfo(ControllerType type); static const ControllerInfo* GetControllerInfo(std::string_view name); + /// Applies an analog deadzone/sensitivity. + static float ApplyAnalogDeadzoneSensitivity(float deadzone, float sensitivity, float value) + { + return (value < deadzone) ? 0.0f : ((value - deadzone) / (1.0f - deadzone) * sensitivity); + } + + /// Returns true if the specified coordinates are inside a circular deadzone. + static bool InCircularDeadzone(float deadzone, float pos_x, float pos_y); + /// Converts a global pad index to a multitap port and slot. static std::tuple ConvertPadToPortAndSlot(u32 index); @@ -124,14 +133,11 @@ public: /// Returns the configuration section for the specified gamepad. static std::string GetSettingsSection(u32 pad); - /// Applies an analog deadzone/sensitivity. - static float ApplyAnalogDeadzoneSensitivity(float deadzone, float sensitivity, float value) - { - return (value < deadzone) ? 0.0f : ((value - deadzone) / (1.0f - deadzone) * sensitivity); - } + /// Returns a printable label for a given port. + static const char* GetPortDisplayName(u32 port, u32 slot, bool mtap); - /// Returns true if the specified coordinates are inside a circular deadzone. - static bool InCircularDeadzone(float deadzone, float pos_x, float pos_y); + /// List of controller indices in the order that they should be displayed. + static const std::array PortDisplayOrder; protected: /// Returns true if automatic analog mode can be used. diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index d6ba4f2e9..2aaeab8f2 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -3743,28 +3743,16 @@ void FullscreenUI::DrawControllerSettingsPage() {(mtap_mode == MultitapMode::Port1Only || mtap_mode == MultitapMode::BothPorts), (mtap_mode == MultitapMode::Port2Only || mtap_mode == MultitapMode::BothPorts)}}; - // we reorder things a little to make it look less silly for mtap - static constexpr const std::array mtap_slot_names = {{'A', 'B', 'C', 'D'}}; - static constexpr const std::array mtap_port_order = {{0, 2, 3, 4, 1, 5, 6, 7}}; - // create the ports - for (u32 global_slot : mtap_port_order) + for (const u32 global_slot : Controller::PortDisplayOrder) { const auto [mtap_port, mtap_slot] = Controller::ConvertPadToPortAndSlot(global_slot); const bool is_mtap_port = Controller::PortAndSlotIsMultitap(mtap_port, mtap_slot); if (is_mtap_port && !mtap_enabled[mtap_port]) continue; - if (mtap_enabled[mtap_port]) - { - MenuHeading(TinyString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}{}")), - mtap_port + 1, mtap_slot_names[mtap_slot])); - } - else - { - MenuHeading( - TinyString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}")), mtap_port + 1)); - } + MenuHeading(TinyString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}")), + Controller::GetPortDisplayName(mtap_port, mtap_slot, mtap_enabled[mtap_port]))); const TinyString section = TinyString::from_format("Pad{}", global_slot + 1); const TinyString type = @@ -3810,16 +3798,9 @@ void FullscreenUI::DrawControllerSettingsPage() Host::TranslateToCString(ci->name, bi.display_name), bi.icon_name, true); } - if (mtap_enabled[mtap_port]) - { - MenuHeading(SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_MICROCHIP, "Controller Port {}{} Macros")), - mtap_port + 1, mtap_slot_names[mtap_slot])); - } - else - { - MenuHeading(SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_MICROCHIP, "Controller Port {} Macros")), - mtap_port + 1)); - } + MenuHeading( + SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_MICROCHIP, "Controller Port {} Macros")), + Controller::GetPortDisplayName(mtap_port, mtap_slot, mtap_enabled[mtap_port]))); for (u32 macro_index = 0; macro_index < InputManager::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_index++) { @@ -3962,17 +3943,9 @@ void FullscreenUI::DrawControllerSettingsPage() if (!ci->settings.empty()) { - if (mtap_enabled[mtap_port]) - { - MenuHeading( - SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {}{} Settings")), - mtap_port + 1, mtap_slot_names[mtap_slot])); - } - else - { - MenuHeading(SmallString::from_format( - fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {} Settings")), mtap_port + 1)); - } + MenuHeading( + SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {} Settings")), + Controller::GetPortDisplayName(mtap_port, mtap_slot, mtap_enabled[mtap_port]))); for (const SettingInfo& si : ci->settings) { diff --git a/src/core/imgui_overlays.cpp b/src/core/imgui_overlays.cpp index 4ad2d1931..f1ebd0114 100644 --- a/src/core/imgui_overlays.cpp +++ b/src/core/imgui_overlays.cpp @@ -628,17 +628,20 @@ void ImGuiManager::DrawInputsOverlay() SmallString text; - for (u32 port = 0; port < NUM_CONTROLLER_AND_CARD_PORTS; port++) + for (const u32 pad : Controller::PortDisplayOrder) { - if (g_settings.controller_types[port] == ControllerType::None) + if (g_settings.controller_types[pad] == ControllerType::None) continue; - const Controller* controller = System::GetController(port); + const Controller* controller = System::GetController(pad); const Controller::ControllerInfo* cinfo = controller ? Controller::GetControllerInfo(controller->GetType()) : nullptr; if (!cinfo) continue; + 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) { @@ -649,11 +652,11 @@ void ImGuiManager::DrawInputsOverlay() 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 + 1u); + text.format(" {}", port_label); } else { - text.format("{} |", port + 1u); + text.format("{} |", port_label); } for (const Controller::ControllerBindingInfo& bi : cinfo->bindings) diff --git a/src/core/multitap.cpp b/src/core/multitap.cpp index 1f1a541ae..b054748b5 100644 --- a/src/core/multitap.cpp +++ b/src/core/multitap.cpp @@ -65,7 +65,8 @@ void Multitap::ResetTransferState() bool Multitap::TransferController(u32 slot, const u8 data_in, u8* data_out) const { - Controller* const selected_controller = Pad::GetController(m_base_index + slot); + const u32 pad_port = Controller::ConvertPortAndSlotToPad(m_base_index, slot); + Controller* const selected_controller = Pad::GetController(pad_port); if (!selected_controller) { *data_out = 0xFF; @@ -77,7 +78,8 @@ bool Multitap::TransferController(u32 slot, const u8 data_in, u8* data_out) cons bool Multitap::TransferMemoryCard(u32 slot, const u8 data_in, u8* data_out) const { - MemoryCard* const selected_memcard = Pad::GetMemoryCard(m_base_index + slot); + const u32 pad_port = Controller::ConvertPortAndSlotToPad(m_base_index, slot); + MemoryCard* const selected_memcard = Pad::GetMemoryCard(pad_port); if (!selected_memcard) { *data_out = 0xFF; diff --git a/src/core/settings.cpp b/src/core/settings.cpp index e9c3febe2..9a9ffc77d 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -369,20 +369,20 @@ void Settings::Load(SettingsInterface& si, SettingsInterface& controller_si) .value_or(DEFAULT_MULTITAP_MODE); const std::array mtap_enabled = {{IsPort1MultitapEnabled(), IsPort2MultitapEnabled()}}; - for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++) + for (u32 pad = 0; pad < NUM_CONTROLLER_AND_CARD_PORTS; pad++) { // Ignore types when multitap not enabled - const auto [port, slot] = Controller::ConvertPadToPortAndSlot(i); - if (Controller::PadIsMultitapSlot(slot) && !mtap_enabled[port]) + const auto [port, slot] = Controller::ConvertPadToPortAndSlot(pad); + if (Controller::PadIsMultitapSlot(pad) && !mtap_enabled[port]) { - controller_types[i] = ControllerType::None; + controller_types[pad] = ControllerType::None; continue; } - const ControllerType default_type = (i == 0) ? DEFAULT_CONTROLLER_1_TYPE : DEFAULT_CONTROLLER_2_TYPE; + 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(i).c_str(), "Type", Controller::GetControllerInfo(default_type)->name)); - controller_types[i] = cinfo ? cinfo->type : default_type; + Controller::GetSettingsSection(pad).c_str(), "Type", Controller::GetControllerInfo(default_type)->name)); + controller_types[pad] = cinfo ? cinfo->type : default_type; } memory_card_types[0] = diff --git a/src/core/settings.h b/src/core/settings.h index feecd8c16..49ba595e1 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -312,7 +312,7 @@ struct Settings } ALWAYS_INLINE bool IsPort2MultitapEnabled() const { - return (multitap_mode == MultitapMode::Port1Only || multitap_mode == MultitapMode::BothPorts); + return (multitap_mode == MultitapMode::Port2Only || multitap_mode == MultitapMode::BothPorts); } ALWAYS_INLINE bool IsMultitapPortEnabled(u32 port) const { diff --git a/src/duckstation-qt/controllersettingswindow.cpp b/src/duckstation-qt/controllersettingswindow.cpp index aafda3847..d5f7050f7 100644 --- a/src/duckstation-qt/controllersettingswindow.cpp +++ b/src/duckstation-qt/controllersettingswindow.cpp @@ -489,12 +489,7 @@ void ControllerSettingsWindow::createWidgets() // load mtap settings const std::array mtap_enabled = getEnabledMultitaps(); - - // we reorder things a little to make it look less silly for mtap - static constexpr const std::array mtap_port_order = {{0, 2, 3, 4, 1, 5, 6, 7}}; - - // create the ports - for (u32 global_slot : mtap_port_order) + for (u32 global_slot : Controller::PortDisplayOrder) { const bool is_mtap_port = Controller::PadIsMultitapSlot(global_slot); const auto [port, slot] = Controller::ConvertPadToPortAndSlot(global_slot); @@ -507,9 +502,9 @@ void ControllerSettingsWindow::createWidgets() const QString display_name(QString::fromUtf8(m_port_bindings[global_slot]->getControllerInfo()->GetDisplayName())); QListWidgetItem* item = new QListWidgetItem(); - item->setText(mtap_enabled[port] ? - (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name)) : - tr("Controller Port %1\n%2").arg(port + 1).arg(display_name)); + item->setText(tr("Controller Port %1\n%2") + .arg(Controller::GetPortDisplayName(port, slot, mtap_enabled[port])) + .arg(display_name)); item->setIcon(m_port_bindings[global_slot]->getIcon()); item->setData(Qt::UserRole, QVariant(global_slot)); m_ui.settingsCategory->addItem(item); @@ -555,9 +550,9 @@ void ControllerSettingsWindow::updateListDescription(u32 global_slot, Controller const QString display_name = QString::fromUtf8(widget->getControllerInfo()->GetDisplayName()); - item->setText(mtap_enabled[port] ? - (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name)) : - tr("Controller Port %1\n%2").arg(port + 1).arg(display_name)); + item->setText(tr("Controller Port %1\n%2") + .arg(Controller::GetPortDisplayName(port, slot, mtap_enabled[port])) + .arg(display_name)); item->setIcon(widget->getIcon()); break; } diff --git a/src/duckstation-qt/controllersettingswindow.h b/src/duckstation-qt/controllersettingswindow.h index 470185dc3..5e79aa568 100644 --- a/src/duckstation-qt/controllersettingswindow.h +++ b/src/duckstation-qt/controllersettingswindow.h @@ -7,7 +7,7 @@ #include "util/input_manager.h" -#include "common/types.h" +#include "core/types.h" #include #include @@ -41,11 +41,6 @@ public: Count }; - enum : u32 - { - MAX_PORTS = 8 - }; - ControllerSettingsWindow(SettingsInterface* game_sif = nullptr, QWidget* parent = nullptr); ~ControllerSettingsWindow(); @@ -121,7 +116,7 @@ private: SettingsInterface* m_editing_settings_interface = nullptr; ControllerGlobalSettingsWidget* m_global_settings = nullptr; - std::array m_port_bindings{}; + std::array m_port_bindings{}; HotkeySettingsWidget* m_hotkey_settings = nullptr; std::vector> m_device_list;