From 6fe6c4e0f62d941a7056fcef5cb44d2339d725ed Mon Sep 17 00:00:00 2001 From: Swordmaster3214 <118647835+Swordmaster3214@users.noreply.github.com> Date: Sun, 28 Sep 2025 15:29:54 -0500 Subject: [PATCH] Enhance Infinity Manager Figure Creator Dialog (#17529) ## Summary This will enhance and add filters for the Figure Creator dialog of Infinity manager, adding selectable filters for the character dropdown and displays the series number after the figure/power disc. ## Changes - Added filter buttons for Disney Infinity 1.0, 2.0, 3.0, and "All" - Character names now display series information (e.g., "Buzz Lightyear (1.0)") - Dynamic dropdown population based on selected filter - Maintains all existing functionality and slot validation ## Benefits - Easier character discovery in large character lists - Better organization by game series --- rpcs3/rpcs3qt/infinity_dialog.cpp | 214 +++++++++++++++++++----------- 1 file changed, 135 insertions(+), 79 deletions(-) diff --git a/rpcs3/rpcs3qt/infinity_dialog.cpp b/rpcs3/rpcs3qt/infinity_dialog.cpp index b172ddad22..5d5617798c 100644 --- a/rpcs3/rpcs3qt/infinity_dialog.cpp +++ b/rpcs3/rpcs3qt/infinity_dialog.cpp @@ -14,6 +14,7 @@ #include #include #include +#include infinity_dialog* infinity_dialog::inst = nullptr; std::array, 9> infinity_dialog::figure_slots = {}; @@ -407,46 +408,94 @@ figure_creator_dialog::figure_creator_dialog(QWidget* parent, u8 slot) { setWindowTitle(tr("Figure Creator")); setObjectName("figure_creator"); - setMinimumSize(QSize(500, 150)); + setMinimumSize(QSize(500, 200)); QVBoxLayout* vbox_panel = new QVBoxLayout(); - QComboBox* combo_figlist = new QComboBox(); - QStringList filterlist; - u32 first_entry = 0; + // Add series filter buttons + QHBoxLayout* hbox_filters = new QHBoxLayout(); + QLabel* filter_label = new QLabel(tr("Filter by Series:")); + QPushButton* btn_all = new QPushButton(tr("All")); + QPushButton* btn_series1 = new QPushButton(tr("1.0")); + QPushButton* btn_series2 = new QPushButton(tr("2.0")); + QPushButton* btn_series3 = new QPushButton(tr("3.0")); - for (const auto& [figure, entry] : list_figures) + // Style the active filter button + btn_all->setCheckable(true); + btn_series1->setCheckable(true); + btn_series2->setCheckable(true); + btn_series3->setCheckable(true); + btn_all->setChecked(true); // Default to "All" + + hbox_filters->addWidget(filter_label); + hbox_filters->addWidget(btn_all); + hbox_filters->addWidget(btn_series1); + hbox_filters->addWidget(btn_series2); + hbox_filters->addWidget(btn_series3); + hbox_filters->addStretch(); + + vbox_panel->addLayout(hbox_filters); + + QComboBox* combo_figlist = new QComboBox(); + + // Lambda to populate the combo box based on series filter + auto populate_combo = [=](int series_filter) -> u32 { - // Only display entry if it is a piece appropriate for the slot - if ((slot == 0 && - ((figure > 0x1E8480 && figure < 0x2DC6BF) || (figure > 0x3D0900 && figure < 0x4C4B3F))) || - ((slot == 1 || slot == 2) && (figure > 0x3D0900 && figure < 0x4C4B3F)) || - ((slot == 3 || slot == 6) && figure < 0x1E847F) || - ((slot == 4 || slot == 5 || slot == 7 || slot == 8) && - (figure > 0x2DC6C0 && figure < 0x3D08FF))) + combo_figlist->clear(); + QStringList filterlist; + u32 first_entry = 0; + + for (const auto& [figure, entry] : list_figures) { const auto& [num, figure_name] = entry; - const u32 qnum = (figure << 8) | num; - QString name = QString::fromStdString(figure_name); - combo_figlist->addItem(name, QVariant(qnum)); - filterlist << std::move(name); - if (first_entry == 0) + + // Apply series filter (0 = all, 1-3 = specific series) + if (series_filter != 0 && num != series_filter) + continue; + + // Only display entry if it is a piece appropriate for the slot + if ((slot == 0 && + ((figure > 0x1E8480 && figure < 0x2DC6BF) || (figure > 0x3D0900 && figure < 0x4C4B3F))) || + ((slot == 1 || slot == 2) && (figure > 0x3D0900 && figure < 0x4C4B3F)) || + ((slot == 3 || slot == 6) && figure < 0x1E847F) || + ((slot == 4 || slot == 5 || slot == 7 || slot == 8) && + (figure > 0x2DC6C0 && figure < 0x3D08FF))) { - first_entry = figure; + const u32 qnum = (figure << 8) | num; + const QString name = QString::fromStdString(figure_name); + // Add series indicator to the name for clarity + QString display_name = QString("%1 (%2.0)").arg(name).arg(num); + combo_figlist->addItem(display_name, QVariant(qnum)); + filterlist << std::move(display_name); + if (first_entry == 0) + { + first_entry = figure; + } } } - } - combo_figlist->addItem(tr("--Unknown--"), QVariant(0xFFFFFFFF)); - combo_figlist->setEditable(true); - combo_figlist->setInsertPolicy(QComboBox::NoInsert); - combo_figlist->model()->sort(0, Qt::AscendingOrder); + combo_figlist->addItem(tr("--Unknown--"), QVariant(0xFFFFFFFF)); + combo_figlist->setEditable(true); + combo_figlist->setInsertPolicy(QComboBox::NoInsert); + combo_figlist->model()->sort(0, Qt::AscendingOrder); - QCompleter* co_compl = new QCompleter(filterlist, this); - co_compl->setCaseSensitivity(Qt::CaseInsensitive); - co_compl->setCompletionMode(QCompleter::PopupCompletion); - co_compl->setFilterMode(Qt::MatchContains); - combo_figlist->setCompleter(co_compl); + // Update completer with new filter list + QCompleter* co_compl = new QCompleter(filterlist, this); + co_compl->setCaseSensitivity(Qt::CaseInsensitive); + co_compl->setCompletionMode(QCompleter::PopupCompletion); + co_compl->setFilterMode(Qt::MatchContains); + combo_figlist->setCompleter(co_compl); + + connect(co_compl, QOverload::of(&QCompleter::activated), [=](const QString& text) + { + combo_figlist->setCurrentIndex(combo_figlist->findText(text)); + }); + + return first_entry; + }; + + // Initially populate with all figures + u32 first_entry = populate_combo(0); vbox_panel->addWidget(combo_figlist); @@ -480,65 +529,72 @@ figure_creator_dialog::figure_creator_dialog(QWidget* parent, u8 slot) setLayout(vbox_panel); - connect(combo_figlist, QOverload::of(&QComboBox::currentIndexChanged), [=](int index) - { - const u32 fig_info = combo_figlist->itemData(index).toUInt(); - if (fig_info != 0xFFFFFFFF) - { - const u32 fig_num = fig_info >> 8; - const u8 series = fig_info & 0xFF; + // Connect filter buttons using QButtonGroup + QButtonGroup* filter_group = new QButtonGroup(this); + filter_group->addButton(btn_all, 0); // ID 0 for "All" + filter_group->addButton(btn_series1, 1); // ID 1 for series 1 + filter_group->addButton(btn_series2, 2); // ID 2 for series 2 + filter_group->addButton(btn_series3, 3); // ID 3 for series 3 - edit_number->setText(QString::number(fig_num)); - edit_series->setText(QString::number(series)); - } - }); + connect(filter_group, QOverload::of(&QButtonGroup::idClicked), [=](int id) + { + populate_combo(id); + }); + + connect(combo_figlist, QOverload::of(&QComboBox::currentIndexChanged), [=](int index) + { + const u32 fig_info = combo_figlist->itemData(index).toUInt(); + if (fig_info != 0xFFFFFFFF) + { + const u32 fig_num = fig_info >> 8; + const u8 series = fig_info & 0xFF; + + edit_number->setText(QString::number(fig_num)); + edit_series->setText(QString::number(series)); + } + }); connect(btn_create, &QAbstractButton::clicked, this, [=, this]() + { + bool ok_num = false, ok_series = false; + const u32 fig_num = edit_number->text().toULong(&ok_num); + if (!ok_num) { - bool ok_num = false, ok_series = false; - const u32 fig_num = edit_number->text().toULong(&ok_num); - if (!ok_num) - { - QMessageBox::warning(this, tr("Error converting value"), tr("Figure number entered is invalid!"), QMessageBox::Ok); - return; - } - const u8 series = edit_series->text().toUShort(&ok_series); - if (!ok_series || series > 3 || series < 1) - { - QMessageBox::warning(this, tr("Error converting value"), tr("Series number entered is invalid!"), QMessageBox::Ok); - return; - } - const auto found_figure = list_figures.find(fig_num); - if (found_figure != list_figures.cend()) - { - s_last_figure_path += QString::fromStdString(found_figure->second.second + ".bin"); - } - else - { - s_last_figure_path += QString("Unknown(%1 %2).bin").arg(fig_num).arg(series); - } + QMessageBox::warning(this, tr("Error converting value"), tr("Figure number entered is invalid!"), QMessageBox::Ok); + return; + } + const u8 series = edit_series->text().toUShort(&ok_series); + if (!ok_series || series > 3 || series < 1) + { + QMessageBox::warning(this, tr("Error converting value"), tr("Series number entered is invalid!"), QMessageBox::Ok); + return; + } + const auto found_figure = list_figures.find(fig_num); + if (found_figure != list_figures.cend()) + { + s_last_figure_path += QString::fromStdString(found_figure->second.second + ".bin"); + } + else + { + s_last_figure_path += QString("Unknown(%1 %2).bin").arg(fig_num).arg(series); + } - m_file_path = QFileDialog::getSaveFileName(this, tr("Create Figure File"), s_last_figure_path, tr("Infinity Figure (*.bin);;")); - if (m_file_path.isEmpty()) - { - return; - } - if (!create_blank_figure(fig_num, series)) - { - QMessageBox::warning(this, tr("Failed to create figure file!"), tr("Failed to create figure file:\n%1").arg(m_file_path), QMessageBox::Ok); - return; - } + m_file_path = QFileDialog::getSaveFileName(this, tr("Create Figure File"), s_last_figure_path, tr("Infinity Figure (*.bin);;")); + if (m_file_path.isEmpty()) + { + return; + } + if (!create_blank_figure(fig_num, series)) + { + QMessageBox::warning(this, tr("Failed to create figure file!"), tr("Failed to create figure file:\n%1").arg(m_file_path), QMessageBox::Ok); + return; + } - s_last_figure_path = QFileInfo(m_file_path).absolutePath() + "/"; - accept(); - }); + s_last_figure_path = QFileInfo(m_file_path).absolutePath() + "/"; + accept(); + }); connect(btn_cancel, &QAbstractButton::clicked, this, &QDialog::reject); - - connect(co_compl, QOverload::of(&QCompleter::activated), [=](const QString& text) - { - combo_figlist->setCurrentIndex(combo_figlist->findText(text)); - }); } bool figure_creator_dialog::create_blank_figure(u32 character, u8 series)