From 540c1696d1d2b9b4ba1b7cf527f8a29e9fc1d67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Locatti?= Date: Sat, 12 Nov 2022 15:31:54 -0300 Subject: Ignore ARM for core count --- src/yuzu/main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 032ff1cbc..72498f52a 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -361,11 +361,10 @@ GMainWindow::GMainWindow(std::unique_ptr config_, bool has_broken_vulkan } } LOG_INFO(Frontend, "Host CPU: {}", cpu_string); -#endif - if (std::optional processor_core = Common::GetProcessorCount()) { LOG_INFO(Frontend, "Host CPU Cores: {}", *processor_core); } +#endif LOG_INFO(Frontend, "Host CPU Threads: {}", processor_count); LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString()); LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", -- cgit v1.2.3 From fb57cd26a1219a5c91d2cb4dec402528f8ba308e Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 13 Nov 2022 11:07:48 -0600 Subject: service: am: Implement cabinet applet backend --- src/yuzu/main.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 032ff1cbc..27c9e1f32 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -26,6 +26,7 @@ #include "configuration/configure_tas.h" #include "core/file_sys/vfs.h" #include "core/file_sys/vfs_real.h" +#include "core/frontend/applets/cabinet.h" #include "core/frontend/applets/controller.h" #include "core/frontend/applets/general_frontend.h" #include "core/frontend/applets/mii_edit.h" @@ -1547,6 +1548,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p system->SetFilesystem(vfs); system->SetAppletFrontendSet({ + nullptr, // Amiibo Manager std::make_unique(*this), // Controller Selector std::make_unique(*this), // Error Display nullptr, // Mii Editor -- cgit v1.2.3 From 9afadca5dc922ac05c7b1557159b277327f40945 Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 13 Nov 2022 13:43:03 -0600 Subject: yuzu: Implement cabinet applet frontend --- src/yuzu/CMakeLists.txt | 3 + src/yuzu/applets/qt_amiibo_manager.cpp | 247 +++++++++++++++++ src/yuzu/applets/qt_amiibo_manager.h | 93 +++++++ src/yuzu/applets/qt_amiibo_manager.ui | 491 +++++++++++++++++++++++++++++++++ src/yuzu/main.cpp | 23 +- src/yuzu/main.h | 9 + 6 files changed, 865 insertions(+), 1 deletion(-) create mode 100644 src/yuzu/applets/qt_amiibo_manager.cpp create mode 100644 src/yuzu/applets/qt_amiibo_manager.h create mode 100644 src/yuzu/applets/qt_amiibo_manager.ui (limited to 'src/yuzu') diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 5cc1fbf32..8571d9c7c 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -18,6 +18,9 @@ add_executable(yuzu about_dialog.cpp about_dialog.h aboutdialog.ui + applets/qt_amiibo_manager.cpp + applets/qt_amiibo_manager.h + applets/qt_amiibo_manager.ui applets/qt_controller.cpp applets/qt_controller.h applets/qt_controller.ui diff --git a/src/yuzu/applets/qt_amiibo_manager.cpp b/src/yuzu/applets/qt_amiibo_manager.cpp new file mode 100644 index 000000000..9c7b15d06 --- /dev/null +++ b/src/yuzu/applets/qt_amiibo_manager.cpp @@ -0,0 +1,247 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include + +#include "common/assert.h" +#include "common/string_util.h" +#include "core/hle/service/nfp/nfp_device.h" +#include "core/hle/service/nfp/nfp_result.h" +#include "input_common/drivers/virtual_amiibo.h" +#include "input_common/main.h" +#include "ui_qt_amiibo_manager.h" +#include "web_service/web_backend.h" +#include "yuzu/applets/qt_amiibo_manager.h" +#include "yuzu/main.h" + +QtAmiiboManagerDialog::QtAmiiboManagerDialog(QWidget* parent, + Core::Frontend::CabinetParameters parameters_, + InputCommon::InputSubsystem* input_subsystem_, + std::shared_ptr nfp_device_) + : QDialog(parent), ui(std::make_unique()), + input_subsystem{input_subsystem_}, nfp_device{nfp_device_}, + parameters(std::move(parameters_)) { + ui->setupUi(this); + + LoadInfo(); + + resize(0, 0); +} + +QtAmiiboManagerDialog::~QtAmiiboManagerDialog() = default; + +int QtAmiiboManagerDialog::exec() { + if (!is_initalized) { + return QDialog::Rejected; + } + return QDialog::exec(); +} + +std::string QtAmiiboManagerDialog::GetName() { + return ui->amiiboCustomNameValue->text().toStdString(); +} + +void QtAmiiboManagerDialog::LoadInfo() { + if (input_subsystem->GetVirtualAmiibo()->ReloadAmiibo() != + InputCommon::VirtualAmiibo::Info::Success) { + return; + } + + if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound && + nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) { + return; + } + nfp_device->Mount(Service::NFP::MountTarget::All); + + Service::NFP::ModelInfo model_info{}; + const auto model_result = nfp_device->GetModelInfo(model_info); + + if (model_result.IsSuccess()) { + const auto amiibo_id = + fmt::format("{:04x}{:02x}{:02x}{:04x}{:02x}02", Common::swap16(model_info.character_id), + model_info.character_variant, model_info.amiibo_type, + model_info.model_number, model_info.series); + LOG_ERROR(Input, "{}", amiibo_id); + LoadAmiiboApiInfo(amiibo_id); + } + + LoadAmiiboData(); + LoadAmiiboGameInfo(); + + ui->amiiboDirectoryValue->setText( + QString::fromStdString(input_subsystem->GetVirtualAmiibo()->GetLastFilePath())); + + SetManagerDescription(); + is_initalized = true; +} + +void QtAmiiboManagerDialog::LoadAmiiboApiInfo(std::string amiibo_id) { + WebService::Client client{"https://amiiboapi.com", {}, {}}; + WebService::Client image_client{"https://raw.githubusercontent.com", {}, {}}; + const auto url_path = fmt::format("/api/amiibo/?id={}", amiibo_id); + + const auto amiibo_json = client.GetJson(url_path, true).returned_data; + if (amiibo_json.empty()) { + ui->amiiboImageLabel->setVisible(false); + ui->amiiboInfoGroup->setVisible(false); + return; + } + + std::string amiibo_series{}; + std::string amiibo_name{}; + std::string amiibo_image_url{}; + std::string amiibo_type{}; + + const auto parsed_amiibo_json_json = nlohmann::json::parse(amiibo_json).at("amiibo"); + parsed_amiibo_json_json.at("amiiboSeries").get_to(amiibo_series); + parsed_amiibo_json_json.at("name").get_to(amiibo_name); + parsed_amiibo_json_json.at("image").get_to(amiibo_image_url); + parsed_amiibo_json_json.at("type").get_to(amiibo_type); + + ui->amiiboSeriesValue->setText(QString::fromStdString(amiibo_series)); + ui->amiiboNameValue->setText(QString::fromStdString(amiibo_name)); + ui->amiiboTypeValue->setText(QString::fromStdString(amiibo_type)); + + if (amiibo_image_url.size() < 34) { + ui->amiiboImageLabel->setVisible(false); + } + + const auto image_url_path = amiibo_image_url.substr(34, amiibo_image_url.size() - 34); + const auto image_data = image_client.GetImage(image_url_path, true).returned_data; + + if (image_data.empty()) { + ui->amiiboImageLabel->setVisible(false); + } + + QPixmap pixmap; + pixmap.loadFromData(reinterpret_cast(image_data.data()), + static_cast(image_data.size())); + pixmap = pixmap.scaled(250, 350, Qt::AspectRatioMode::KeepAspectRatio, + Qt::TransformationMode::SmoothTransformation); + ui->amiiboImageLabel->setPixmap(pixmap); +} + +void QtAmiiboManagerDialog::LoadAmiiboData() { + Service::NFP::RegisterInfo register_info{}; + Service::NFP::CommonInfo common_info{}; + const auto register_result = nfp_device->GetRegisterInfo(register_info); + const auto common_result = nfp_device->GetCommonInfo(common_info); + + if (register_result.IsFailure()) { + ui->creationDateValue->setDisabled(true); + ui->modificationDateValue->setDisabled(true); + ui->amiiboCustomNameValue->setReadOnly(false); + ui->amiiboOwnerValue->setReadOnly(false); + return; + } + + if (parameters.mode == Service::NFP::CabinetMode::StartNicknameAndOwnerSettings) { + ui->creationDateValue->setDisabled(true); + ui->modificationDateValue->setDisabled(true); + } + + const auto amiibo_name = std::string(register_info.amiibo_name.data()); + const auto owner_name = Common::UTF16ToUTF8(register_info.mii_char_info.name.data()); + const auto creation_date = + QDate(register_info.creation_date.year, register_info.creation_date.month, + register_info.creation_date.day); + + ui->amiiboCustomNameValue->setText(QString::fromStdString(amiibo_name)); + ui->amiiboOwnerValue->setText(QString::fromStdString(owner_name)); + ui->amiiboCustomNameValue->setReadOnly(true); + ui->amiiboOwnerValue->setReadOnly(true); + ui->creationDateValue->setDate(creation_date); + + if (common_result.IsFailure()) { + ui->modificationDateValue->setDisabled(true); + return; + } + + const auto modification_date = + QDate(common_info.last_write_date.year, common_info.last_write_date.month, + common_info.last_write_date.day); + ui->modificationDateValue->setDate(modification_date); +} + +void QtAmiiboManagerDialog::LoadAmiiboGameInfo() { + u32 application_area_id{}; + const auto application_result = nfp_device->GetApplicationAreaId(application_area_id); + + if (application_result.IsFailure()) { + ui->gameIdValue->setVisible(false); + ui->gameIdLabel->setText(tr("No game data present")); + return; + } + + SetGameDataName(application_area_id); +} + +void QtAmiiboManagerDialog::SetGameDataName(u32 application_area_id) { + const std::array, 12> game_name_list = { + // 3ds, wii u + std::pair{0x10110E00, QStringLiteral("Super Smash Bros (3DS/WiiU)")}, + {0x00132600, QStringLiteral("Mario & Luigi: Paper Jam")}, + {0x0014F000, QStringLiteral("Animal Crossing: Happy Home Designer")}, + {0x00152600, QStringLiteral("Chibi-Robo!: Zip Lash")}, + {0x10161f00, QStringLiteral("Mario Party 10")}, + {0x1019C800, QStringLiteral("The Legend of Zelda: Twilight Princess HD")}, + // switch + {0x10162B00, QStringLiteral("Splatoon 2")}, + {0x1016e100, QStringLiteral("Shovel Knight: Treasure Trove")}, + {0x1019C800, QStringLiteral("The Legend of Zelda: Breath of the Wild")}, + {0x34F80200, QStringLiteral("Super Smash Bros. Ultimate")}, + {0x38600500, QStringLiteral("Splatoon 3")}, + {0x3B440400, QStringLiteral("The Legend of Zelda: Link's Awakening")}, + }; + + for (const auto& [game_id, game_name] : game_name_list) { + if (application_area_id == game_id) { + ui->gameIdValue->setText(game_name); + return; + } + } + + const auto application_area_string = fmt::format("{:016x}", application_area_id); + ui->gameIdValue->setText(QString::fromStdString(application_area_string)); +} + +void QtAmiiboManagerDialog::SetManagerDescription() { + switch (parameters.mode) { + case Service::NFP::CabinetMode::StartFormatter: + ui->cabinetActionDescriptionLabel->setText( + tr("The following amiibo data will be formated:")); + break; + case Service::NFP::CabinetMode::StartGameDataEraser: + ui->cabinetActionDescriptionLabel->setText(tr("The following game data will removed:")); + break; + case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: + ui->cabinetActionDescriptionLabel->setText(tr("Set nickname and owner:")); + break; + case Service::NFP::CabinetMode::StartRestorer: + ui->cabinetActionDescriptionLabel->setText(tr("Do you wish to restore this amiibo:")); + break; + } +} + +QtAmiiboManager::QtAmiiboManager(GMainWindow& parent) { + connect(this, &QtAmiiboManager::MainWindowShowAmiiboManager, &parent, + &GMainWindow::AmiiboManagerShowDialog, Qt::QueuedConnection); + connect(&parent, &GMainWindow::AmiiboManagerFinished, this, + &QtAmiiboManager::MainWindowFinished, Qt::QueuedConnection); +} + +QtAmiiboManager::~QtAmiiboManager() = default; + +void QtAmiiboManager::ShowCabinetApplet(std::function callback_, + const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device) const { + callback = std::move(callback_); + emit MainWindowShowAmiiboManager(parameters, nfp_device); +} + +void QtAmiiboManager::MainWindowFinished(bool is_success, std::string name) { + callback(is_success, name); +} diff --git a/src/yuzu/applets/qt_amiibo_manager.h b/src/yuzu/applets/qt_amiibo_manager.h new file mode 100644 index 000000000..3f5866ed7 --- /dev/null +++ b/src/yuzu/applets/qt_amiibo_manager.h @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include "core/frontend/applets/cabinet.h" + +class GMainWindow; +class QCheckBox; +class QComboBox; +class QDialogButtonBox; +class QGroupBox; +class QLabel; + +class InputProfiles; + +namespace InputCommon { +class InputSubsystem; +} + +namespace Ui { +class QtAmiiboManagerDialog; +} + +namespace Core { +class System; +} + +namespace Core::HID { +class HIDCore; +enum class NpadStyleIndex : u8; +} // namespace Core::HID + +namespace Service::NFP { +class NfpDevice; +} // namespace Service::NFP + +class QtAmiiboManagerDialog final : public QDialog { + Q_OBJECT + +public: + explicit QtAmiiboManagerDialog(QWidget* parent, Core::Frontend::CabinetParameters parameters_, + InputCommon::InputSubsystem* input_subsystem_, + std::shared_ptr nfp_device_); + ~QtAmiiboManagerDialog() override; + + int exec() override; + + std::string GetName(); + +private: + void LoadInfo(); + void LoadAmiiboApiInfo(std::string amiibo_id); + void LoadAmiiboData(); + void LoadAmiiboGameInfo(); + void SetGameDataName(u32 application_area_id); + void SetManagerDescription(); + + std::unique_ptr ui; + + InputCommon::InputSubsystem* input_subsystem; + std::shared_ptr nfp_device; + + // Parameters sent in from the backend HLE applet. + Core::Frontend::CabinetParameters parameters; + + // If false amiibo manager failed to load + bool is_initalized{}; +}; + +class QtAmiiboManager final : public QObject, public Core::Frontend::CabinetApplet { + Q_OBJECT + +public: + explicit QtAmiiboManager(GMainWindow& parent); + ~QtAmiiboManager() override; + + void ShowCabinetApplet(std::function callback_, + const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device) const override; + +signals: + void MainWindowShowAmiiboManager(const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device) const; + +private: + void MainWindowFinished(bool is_success, std::string name); + + mutable std::function callback; +}; diff --git a/src/yuzu/applets/qt_amiibo_manager.ui b/src/yuzu/applets/qt_amiibo_manager.ui new file mode 100644 index 000000000..eb6eabe59 --- /dev/null +++ b/src/yuzu/applets/qt_amiibo_manager.ui @@ -0,0 +1,491 @@ + + + QtAmiiboManagerDialog + + + + 0 + 0 + 839 + 500 + + + + Amiibo Manager + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 10 + + + 20 + + + 15 + + + 0 + + + 15 + + + + + + 12 + 75 + true + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 20 + + + 15 + + + + + + 250 + 350 + + + + + 236 + 350 + + + + + + + Qt::AlignCenter + + + + + + + 20 + + + 8 + + + 15 + + + + + Amiibo Info + + + + + + + + Series + + + + + + + + 0 + 0 + + + + true + + + + + + + Type + + + + + + + + 0 + 0 + + + + true + + + + + + + Name + + + + + + + + 0 + 0 + + + + true + + + + + + + + + + + + Amiibo Data + + + + + + + + Custom Name + + + + + + + + 0 + 0 + + + + 10 + + + + + + + Owner + + + + + + + + 0 + 0 + + + + 10 + + + + + + + Creation Date + + + + + + + true + + + + 1970 + 1 + 1 + + + + dd/MM/yyyy + + + + + + + Modification Date + + + + + + + true + + + + 1970 + 1 + 1 + + + + dd/MM/yyyy + + + + + + + + + + + + + 500 + 0 + + + + Game Data + + + + + + Game Id + + + + + + + + 0 + 0 + + + + true + + + + + + + + + + + 500 + 0 + + + + Mount Amiibo + + + + + + ... + + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 60 + 20 + + + + + + + + File Path + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + 15 + + + 15 + + + 8 + + + 20 + + + 8 + + + + + true + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + + + + buttonBox + accepted() + QtAmiiboManagerDialog + accept() + + + buttonBox + rejected() + QtAmiiboManagerDialog + reject() + + + diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 27c9e1f32..27266cae3 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -15,6 +15,7 @@ #endif // VFS includes must be before glad as they will conflict with Windows file api, which uses defines. +#include "applets/qt_amiibo_manager.h" #include "applets/qt_controller.h" #include "applets/qt_error.h" #include "applets/qt_profile_select.h" @@ -550,6 +551,11 @@ void GMainWindow::RegisterMetaTypes() { // Register applet types + // Cabinet Applet + qRegisterMetaType("Core::Frontend::CabinetParameters"); + qRegisterMetaType>( + "std::shared_ptr"); + // Controller Applet qRegisterMetaType("Core::Frontend::ControllerParameters"); @@ -571,6 +577,21 @@ void GMainWindow::RegisterMetaTypes() { qRegisterMetaType("Core::SystemResultStatus"); } +void GMainWindow::AmiiboManagerShowDialog(const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device) { + QtAmiiboManagerDialog dialog(this, parameters, input_subsystem.get(), nfp_device); + + dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | + Qt::WindowTitleHint | Qt::WindowSystemMenuHint); + dialog.setWindowModality(Qt::WindowModal); + if (dialog.exec() == QDialog::Rejected) { + emit AmiiboManagerFinished(false, {}); + return; + } + + emit AmiiboManagerFinished(true, dialog.GetName()); +} + void GMainWindow::ControllerSelectorReconfigureControllers( const Core::Frontend::ControllerParameters& parameters) { QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get(), *system); @@ -1548,7 +1569,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p system->SetFilesystem(vfs); system->SetAppletFrontendSet({ - nullptr, // Amiibo Manager + std::make_unique(*this), // Amiibo Manager std::make_unique(*this), // Controller Selector std::make_unique(*this), // Error Display nullptr, // Mii Editor diff --git a/src/yuzu/main.h b/src/yuzu/main.h index b73f550dd..2724ecd52 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -55,6 +55,7 @@ class System; } // namespace Core namespace Core::Frontend { +struct CabinetParameters; struct ControllerParameters; struct InlineAppearParameters; struct InlineTextParameters; @@ -82,6 +83,10 @@ enum class SwkbdReplyType : u32; enum class WebExitReason : u32; } // namespace Service::AM::Applets +namespace Service::NFP { +class NfpDevice; +} // namespace Service::NFP + namespace Ui { class MainWindow; } @@ -149,6 +154,8 @@ signals: void UpdateInstallProgress(); + void AmiiboManagerFinished(bool is_success, std::string name); + void ControllerSelectorReconfigureFinished(); void ErrorDisplayFinished(); @@ -170,6 +177,8 @@ public slots: void OnExecuteProgram(std::size_t program_index); void OnExit(); void OnSaveConfig(); + void AmiiboManagerShowDialog(const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device); void ControllerSelectorReconfigureControllers( const Core::Frontend::ControllerParameters& parameters); void SoftwareKeyboardInitialize( -- cgit v1.2.3 From 75e6ec85e107d6e5422d882b97faaa813970d42e Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 13 Nov 2022 15:14:08 -0600 Subject: general: Address review comments --- src/yuzu/CMakeLists.txt | 6 +- src/yuzu/applets/qt_amiibo_manager.cpp | 247 ---------------- src/yuzu/applets/qt_amiibo_manager.h | 93 ------ src/yuzu/applets/qt_amiibo_manager.ui | 491 ------------------------------- src/yuzu/applets/qt_amiibo_settings.cpp | 260 +++++++++++++++++ src/yuzu/applets/qt_amiibo_settings.h | 83 ++++++ src/yuzu/applets/qt_amiibo_settings.ui | 494 ++++++++++++++++++++++++++++++++ src/yuzu/main.cpp | 14 +- src/yuzu/main.h | 6 +- 9 files changed, 850 insertions(+), 844 deletions(-) delete mode 100644 src/yuzu/applets/qt_amiibo_manager.cpp delete mode 100644 src/yuzu/applets/qt_amiibo_manager.h delete mode 100644 src/yuzu/applets/qt_amiibo_manager.ui create mode 100644 src/yuzu/applets/qt_amiibo_settings.cpp create mode 100644 src/yuzu/applets/qt_amiibo_settings.h create mode 100644 src/yuzu/applets/qt_amiibo_settings.ui (limited to 'src/yuzu') diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 8571d9c7c..adad36221 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -18,9 +18,9 @@ add_executable(yuzu about_dialog.cpp about_dialog.h aboutdialog.ui - applets/qt_amiibo_manager.cpp - applets/qt_amiibo_manager.h - applets/qt_amiibo_manager.ui + applets/qt_amiibo_settings.cpp + applets/qt_amiibo_settings.h + applets/qt_amiibo_settings.ui applets/qt_controller.cpp applets/qt_controller.h applets/qt_controller.ui diff --git a/src/yuzu/applets/qt_amiibo_manager.cpp b/src/yuzu/applets/qt_amiibo_manager.cpp deleted file mode 100644 index 9c7b15d06..000000000 --- a/src/yuzu/applets/qt_amiibo_manager.cpp +++ /dev/null @@ -1,247 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include -#include - -#include "common/assert.h" -#include "common/string_util.h" -#include "core/hle/service/nfp/nfp_device.h" -#include "core/hle/service/nfp/nfp_result.h" -#include "input_common/drivers/virtual_amiibo.h" -#include "input_common/main.h" -#include "ui_qt_amiibo_manager.h" -#include "web_service/web_backend.h" -#include "yuzu/applets/qt_amiibo_manager.h" -#include "yuzu/main.h" - -QtAmiiboManagerDialog::QtAmiiboManagerDialog(QWidget* parent, - Core::Frontend::CabinetParameters parameters_, - InputCommon::InputSubsystem* input_subsystem_, - std::shared_ptr nfp_device_) - : QDialog(parent), ui(std::make_unique()), - input_subsystem{input_subsystem_}, nfp_device{nfp_device_}, - parameters(std::move(parameters_)) { - ui->setupUi(this); - - LoadInfo(); - - resize(0, 0); -} - -QtAmiiboManagerDialog::~QtAmiiboManagerDialog() = default; - -int QtAmiiboManagerDialog::exec() { - if (!is_initalized) { - return QDialog::Rejected; - } - return QDialog::exec(); -} - -std::string QtAmiiboManagerDialog::GetName() { - return ui->amiiboCustomNameValue->text().toStdString(); -} - -void QtAmiiboManagerDialog::LoadInfo() { - if (input_subsystem->GetVirtualAmiibo()->ReloadAmiibo() != - InputCommon::VirtualAmiibo::Info::Success) { - return; - } - - if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound && - nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) { - return; - } - nfp_device->Mount(Service::NFP::MountTarget::All); - - Service::NFP::ModelInfo model_info{}; - const auto model_result = nfp_device->GetModelInfo(model_info); - - if (model_result.IsSuccess()) { - const auto amiibo_id = - fmt::format("{:04x}{:02x}{:02x}{:04x}{:02x}02", Common::swap16(model_info.character_id), - model_info.character_variant, model_info.amiibo_type, - model_info.model_number, model_info.series); - LOG_ERROR(Input, "{}", amiibo_id); - LoadAmiiboApiInfo(amiibo_id); - } - - LoadAmiiboData(); - LoadAmiiboGameInfo(); - - ui->amiiboDirectoryValue->setText( - QString::fromStdString(input_subsystem->GetVirtualAmiibo()->GetLastFilePath())); - - SetManagerDescription(); - is_initalized = true; -} - -void QtAmiiboManagerDialog::LoadAmiiboApiInfo(std::string amiibo_id) { - WebService::Client client{"https://amiiboapi.com", {}, {}}; - WebService::Client image_client{"https://raw.githubusercontent.com", {}, {}}; - const auto url_path = fmt::format("/api/amiibo/?id={}", amiibo_id); - - const auto amiibo_json = client.GetJson(url_path, true).returned_data; - if (amiibo_json.empty()) { - ui->amiiboImageLabel->setVisible(false); - ui->amiiboInfoGroup->setVisible(false); - return; - } - - std::string amiibo_series{}; - std::string amiibo_name{}; - std::string amiibo_image_url{}; - std::string amiibo_type{}; - - const auto parsed_amiibo_json_json = nlohmann::json::parse(amiibo_json).at("amiibo"); - parsed_amiibo_json_json.at("amiiboSeries").get_to(amiibo_series); - parsed_amiibo_json_json.at("name").get_to(amiibo_name); - parsed_amiibo_json_json.at("image").get_to(amiibo_image_url); - parsed_amiibo_json_json.at("type").get_to(amiibo_type); - - ui->amiiboSeriesValue->setText(QString::fromStdString(amiibo_series)); - ui->amiiboNameValue->setText(QString::fromStdString(amiibo_name)); - ui->amiiboTypeValue->setText(QString::fromStdString(amiibo_type)); - - if (amiibo_image_url.size() < 34) { - ui->amiiboImageLabel->setVisible(false); - } - - const auto image_url_path = amiibo_image_url.substr(34, amiibo_image_url.size() - 34); - const auto image_data = image_client.GetImage(image_url_path, true).returned_data; - - if (image_data.empty()) { - ui->amiiboImageLabel->setVisible(false); - } - - QPixmap pixmap; - pixmap.loadFromData(reinterpret_cast(image_data.data()), - static_cast(image_data.size())); - pixmap = pixmap.scaled(250, 350, Qt::AspectRatioMode::KeepAspectRatio, - Qt::TransformationMode::SmoothTransformation); - ui->amiiboImageLabel->setPixmap(pixmap); -} - -void QtAmiiboManagerDialog::LoadAmiiboData() { - Service::NFP::RegisterInfo register_info{}; - Service::NFP::CommonInfo common_info{}; - const auto register_result = nfp_device->GetRegisterInfo(register_info); - const auto common_result = nfp_device->GetCommonInfo(common_info); - - if (register_result.IsFailure()) { - ui->creationDateValue->setDisabled(true); - ui->modificationDateValue->setDisabled(true); - ui->amiiboCustomNameValue->setReadOnly(false); - ui->amiiboOwnerValue->setReadOnly(false); - return; - } - - if (parameters.mode == Service::NFP::CabinetMode::StartNicknameAndOwnerSettings) { - ui->creationDateValue->setDisabled(true); - ui->modificationDateValue->setDisabled(true); - } - - const auto amiibo_name = std::string(register_info.amiibo_name.data()); - const auto owner_name = Common::UTF16ToUTF8(register_info.mii_char_info.name.data()); - const auto creation_date = - QDate(register_info.creation_date.year, register_info.creation_date.month, - register_info.creation_date.day); - - ui->amiiboCustomNameValue->setText(QString::fromStdString(amiibo_name)); - ui->amiiboOwnerValue->setText(QString::fromStdString(owner_name)); - ui->amiiboCustomNameValue->setReadOnly(true); - ui->amiiboOwnerValue->setReadOnly(true); - ui->creationDateValue->setDate(creation_date); - - if (common_result.IsFailure()) { - ui->modificationDateValue->setDisabled(true); - return; - } - - const auto modification_date = - QDate(common_info.last_write_date.year, common_info.last_write_date.month, - common_info.last_write_date.day); - ui->modificationDateValue->setDate(modification_date); -} - -void QtAmiiboManagerDialog::LoadAmiiboGameInfo() { - u32 application_area_id{}; - const auto application_result = nfp_device->GetApplicationAreaId(application_area_id); - - if (application_result.IsFailure()) { - ui->gameIdValue->setVisible(false); - ui->gameIdLabel->setText(tr("No game data present")); - return; - } - - SetGameDataName(application_area_id); -} - -void QtAmiiboManagerDialog::SetGameDataName(u32 application_area_id) { - const std::array, 12> game_name_list = { - // 3ds, wii u - std::pair{0x10110E00, QStringLiteral("Super Smash Bros (3DS/WiiU)")}, - {0x00132600, QStringLiteral("Mario & Luigi: Paper Jam")}, - {0x0014F000, QStringLiteral("Animal Crossing: Happy Home Designer")}, - {0x00152600, QStringLiteral("Chibi-Robo!: Zip Lash")}, - {0x10161f00, QStringLiteral("Mario Party 10")}, - {0x1019C800, QStringLiteral("The Legend of Zelda: Twilight Princess HD")}, - // switch - {0x10162B00, QStringLiteral("Splatoon 2")}, - {0x1016e100, QStringLiteral("Shovel Knight: Treasure Trove")}, - {0x1019C800, QStringLiteral("The Legend of Zelda: Breath of the Wild")}, - {0x34F80200, QStringLiteral("Super Smash Bros. Ultimate")}, - {0x38600500, QStringLiteral("Splatoon 3")}, - {0x3B440400, QStringLiteral("The Legend of Zelda: Link's Awakening")}, - }; - - for (const auto& [game_id, game_name] : game_name_list) { - if (application_area_id == game_id) { - ui->gameIdValue->setText(game_name); - return; - } - } - - const auto application_area_string = fmt::format("{:016x}", application_area_id); - ui->gameIdValue->setText(QString::fromStdString(application_area_string)); -} - -void QtAmiiboManagerDialog::SetManagerDescription() { - switch (parameters.mode) { - case Service::NFP::CabinetMode::StartFormatter: - ui->cabinetActionDescriptionLabel->setText( - tr("The following amiibo data will be formated:")); - break; - case Service::NFP::CabinetMode::StartGameDataEraser: - ui->cabinetActionDescriptionLabel->setText(tr("The following game data will removed:")); - break; - case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: - ui->cabinetActionDescriptionLabel->setText(tr("Set nickname and owner:")); - break; - case Service::NFP::CabinetMode::StartRestorer: - ui->cabinetActionDescriptionLabel->setText(tr("Do you wish to restore this amiibo:")); - break; - } -} - -QtAmiiboManager::QtAmiiboManager(GMainWindow& parent) { - connect(this, &QtAmiiboManager::MainWindowShowAmiiboManager, &parent, - &GMainWindow::AmiiboManagerShowDialog, Qt::QueuedConnection); - connect(&parent, &GMainWindow::AmiiboManagerFinished, this, - &QtAmiiboManager::MainWindowFinished, Qt::QueuedConnection); -} - -QtAmiiboManager::~QtAmiiboManager() = default; - -void QtAmiiboManager::ShowCabinetApplet(std::function callback_, - const Core::Frontend::CabinetParameters& parameters, - std::shared_ptr nfp_device) const { - callback = std::move(callback_); - emit MainWindowShowAmiiboManager(parameters, nfp_device); -} - -void QtAmiiboManager::MainWindowFinished(bool is_success, std::string name) { - callback(is_success, name); -} diff --git a/src/yuzu/applets/qt_amiibo_manager.h b/src/yuzu/applets/qt_amiibo_manager.h deleted file mode 100644 index 3f5866ed7..000000000 --- a/src/yuzu/applets/qt_amiibo_manager.h +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include "core/frontend/applets/cabinet.h" - -class GMainWindow; -class QCheckBox; -class QComboBox; -class QDialogButtonBox; -class QGroupBox; -class QLabel; - -class InputProfiles; - -namespace InputCommon { -class InputSubsystem; -} - -namespace Ui { -class QtAmiiboManagerDialog; -} - -namespace Core { -class System; -} - -namespace Core::HID { -class HIDCore; -enum class NpadStyleIndex : u8; -} // namespace Core::HID - -namespace Service::NFP { -class NfpDevice; -} // namespace Service::NFP - -class QtAmiiboManagerDialog final : public QDialog { - Q_OBJECT - -public: - explicit QtAmiiboManagerDialog(QWidget* parent, Core::Frontend::CabinetParameters parameters_, - InputCommon::InputSubsystem* input_subsystem_, - std::shared_ptr nfp_device_); - ~QtAmiiboManagerDialog() override; - - int exec() override; - - std::string GetName(); - -private: - void LoadInfo(); - void LoadAmiiboApiInfo(std::string amiibo_id); - void LoadAmiiboData(); - void LoadAmiiboGameInfo(); - void SetGameDataName(u32 application_area_id); - void SetManagerDescription(); - - std::unique_ptr ui; - - InputCommon::InputSubsystem* input_subsystem; - std::shared_ptr nfp_device; - - // Parameters sent in from the backend HLE applet. - Core::Frontend::CabinetParameters parameters; - - // If false amiibo manager failed to load - bool is_initalized{}; -}; - -class QtAmiiboManager final : public QObject, public Core::Frontend::CabinetApplet { - Q_OBJECT - -public: - explicit QtAmiiboManager(GMainWindow& parent); - ~QtAmiiboManager() override; - - void ShowCabinetApplet(std::function callback_, - const Core::Frontend::CabinetParameters& parameters, - std::shared_ptr nfp_device) const override; - -signals: - void MainWindowShowAmiiboManager(const Core::Frontend::CabinetParameters& parameters, - std::shared_ptr nfp_device) const; - -private: - void MainWindowFinished(bool is_success, std::string name); - - mutable std::function callback; -}; diff --git a/src/yuzu/applets/qt_amiibo_manager.ui b/src/yuzu/applets/qt_amiibo_manager.ui deleted file mode 100644 index eb6eabe59..000000000 --- a/src/yuzu/applets/qt_amiibo_manager.ui +++ /dev/null @@ -1,491 +0,0 @@ - - - QtAmiiboManagerDialog - - - - 0 - 0 - 839 - 500 - - - - Amiibo Manager - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 10 - - - 20 - - - 15 - - - 0 - - - 15 - - - - - - 12 - 75 - true - - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 20 - - - 15 - - - - - - 250 - 350 - - - - - 236 - 350 - - - - - - - Qt::AlignCenter - - - - - - - 20 - - - 8 - - - 15 - - - - - Amiibo Info - - - - - - - - Series - - - - - - - - 0 - 0 - - - - true - - - - - - - Type - - - - - - - - 0 - 0 - - - - true - - - - - - - Name - - - - - - - - 0 - 0 - - - - true - - - - - - - - - - - - Amiibo Data - - - - - - - - Custom Name - - - - - - - - 0 - 0 - - - - 10 - - - - - - - Owner - - - - - - - - 0 - 0 - - - - 10 - - - - - - - Creation Date - - - - - - - true - - - - 1970 - 1 - 1 - - - - dd/MM/yyyy - - - - - - - Modification Date - - - - - - - true - - - - 1970 - 1 - 1 - - - - dd/MM/yyyy - - - - - - - - - - - - - 500 - 0 - - - - Game Data - - - - - - Game Id - - - - - - - - 0 - 0 - - - - true - - - - - - - - - - - 500 - 0 - - - - Mount Amiibo - - - - - - ... - - - - - - - Qt::Horizontal - - - QSizePolicy::Maximum - - - - 60 - 20 - - - - - - - - File Path - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - - 15 - - - 15 - - - 8 - - - 20 - - - 8 - - - - - true - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - - - - - buttonBox - accepted() - QtAmiiboManagerDialog - accept() - - - buttonBox - rejected() - QtAmiiboManagerDialog - reject() - - - diff --git a/src/yuzu/applets/qt_amiibo_settings.cpp b/src/yuzu/applets/qt_amiibo_settings.cpp new file mode 100644 index 000000000..efb7f6ecc --- /dev/null +++ b/src/yuzu/applets/qt_amiibo_settings.cpp @@ -0,0 +1,260 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include + +#include "common/assert.h" +#include "common/string_util.h" +#include "core/hle/service/nfp/nfp_device.h" +#include "core/hle/service/nfp/nfp_result.h" +#include "input_common/drivers/virtual_amiibo.h" +#include "input_common/main.h" +#include "ui_qt_amiibo_settings.h" +#include "web_service/web_backend.h" +#include "yuzu/applets/qt_amiibo_settings.h" +#include "yuzu/main.h" + +QtAmiiboSettingsDialog::QtAmiiboSettingsDialog(QWidget* parent, + Core::Frontend::CabinetParameters parameters_, + InputCommon::InputSubsystem* input_subsystem_, + std::shared_ptr nfp_device_) + : QDialog(parent), ui(std::make_unique()), + input_subsystem{input_subsystem_}, nfp_device{std::move(nfp_device_)}, + parameters(std::move(parameters_)) { + ui->setupUi(this); + + LoadInfo(); + + resize(0, 0); +} + +QtAmiiboSettingsDialog::~QtAmiiboSettingsDialog() = default; + +int QtAmiiboSettingsDialog::exec() { + if (!is_initalized) { + return QDialog::Rejected; + } + return QDialog::exec(); +} + +std::string QtAmiiboSettingsDialog::GetName() const { + return ui->amiiboCustomNameValue->text().toStdString(); +} + +void QtAmiiboSettingsDialog::LoadInfo() { + if (input_subsystem->GetVirtualAmiibo()->ReloadAmiibo() != + InputCommon::VirtualAmiibo::Info::Success) { + return; + } + + if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound && + nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) { + return; + } + nfp_device->Mount(Service::NFP::MountTarget::All); + + LoadAmiiboInfo(); + LoadAmiiboData(); + LoadAmiiboGameInfo(); + + ui->amiiboDirectoryValue->setText( + QString::fromStdString(input_subsystem->GetVirtualAmiibo()->GetLastFilePath())); + + SetSettingsDescription(); + is_initalized = true; +} + +void QtAmiiboSettingsDialog::LoadAmiiboInfo() { + Service::NFP::ModelInfo model_info{}; + const auto model_result = nfp_device->GetModelInfo(model_info); + + if (model_result.IsFailure()) { + ui->amiiboImageLabel->setVisible(false); + ui->amiiboInfoGroup->setVisible(false); + return; + } + + const auto amiibo_id = + fmt::format("{:04x}{:02x}{:02x}{:04x}{:02x}02", Common::swap16(model_info.character_id), + model_info.character_variant, model_info.amiibo_type, model_info.model_number, + model_info.series); + + LOG_DEBUG(Frontend, "Loading amiibo id {}", amiibo_id); + // Note: This function is not being used until we host the images on our server + // LoadAmiiboApiInfo(amiibo_id); + ui->amiiboImageLabel->setVisible(false); + ui->amiiboInfoGroup->setVisible(false); +} + +void QtAmiiboSettingsDialog::LoadAmiiboApiInfo(std::string_view amiibo_id) { + // TODO: Host this data on our website + WebService::Client client{"https://amiiboapi.com", {}, {}}; + WebService::Client image_client{"https://raw.githubusercontent.com", {}, {}}; + const auto url_path = fmt::format("/api/amiibo/?id={}", amiibo_id); + + const auto amiibo_json = client.GetJson(url_path, true).returned_data; + if (amiibo_json.empty()) { + ui->amiiboImageLabel->setVisible(false); + ui->amiiboInfoGroup->setVisible(false); + return; + } + + std::string amiibo_series{}; + std::string amiibo_name{}; + std::string amiibo_image_url{}; + std::string amiibo_type{}; + + const auto parsed_amiibo_json_json = nlohmann::json::parse(amiibo_json).at("amiibo"); + parsed_amiibo_json_json.at("amiiboSeries").get_to(amiibo_series); + parsed_amiibo_json_json.at("name").get_to(amiibo_name); + parsed_amiibo_json_json.at("image").get_to(amiibo_image_url); + parsed_amiibo_json_json.at("type").get_to(amiibo_type); + + ui->amiiboSeriesValue->setText(QString::fromStdString(amiibo_series)); + ui->amiiboNameValue->setText(QString::fromStdString(amiibo_name)); + ui->amiiboTypeValue->setText(QString::fromStdString(amiibo_type)); + + if (amiibo_image_url.size() < 34) { + ui->amiiboImageLabel->setVisible(false); + } + + const auto image_url_path = amiibo_image_url.substr(34, amiibo_image_url.size() - 34); + const auto image_data = image_client.GetImage(image_url_path, true).returned_data; + + if (image_data.empty()) { + ui->amiiboImageLabel->setVisible(false); + } + + QPixmap pixmap; + pixmap.loadFromData(reinterpret_cast(image_data.data()), + static_cast(image_data.size())); + pixmap = pixmap.scaled(250, 350, Qt::AspectRatioMode::KeepAspectRatio, + Qt::TransformationMode::SmoothTransformation); + ui->amiiboImageLabel->setPixmap(pixmap); +} + +void QtAmiiboSettingsDialog::LoadAmiiboData() { + Service::NFP::RegisterInfo register_info{}; + Service::NFP::CommonInfo common_info{}; + const auto register_result = nfp_device->GetRegisterInfo(register_info); + const auto common_result = nfp_device->GetCommonInfo(common_info); + + if (register_result.IsFailure()) { + ui->creationDateValue->setDisabled(true); + ui->modificationDateValue->setDisabled(true); + ui->amiiboCustomNameValue->setReadOnly(false); + ui->amiiboOwnerValue->setReadOnly(false); + return; + } + + if (parameters.mode == Service::NFP::CabinetMode::StartNicknameAndOwnerSettings) { + ui->creationDateValue->setDisabled(true); + ui->modificationDateValue->setDisabled(true); + } + + const auto amiibo_name = std::string(register_info.amiibo_name.data()); + const auto owner_name = Common::UTF16ToUTF8(register_info.mii_char_info.name.data()); + const auto creation_date = + QDate(register_info.creation_date.year, register_info.creation_date.month, + register_info.creation_date.day); + + ui->amiiboCustomNameValue->setText(QString::fromStdString(amiibo_name)); + ui->amiiboOwnerValue->setText(QString::fromStdString(owner_name)); + ui->amiiboCustomNameValue->setReadOnly(true); + ui->amiiboOwnerValue->setReadOnly(true); + ui->creationDateValue->setDate(creation_date); + + if (common_result.IsFailure()) { + ui->modificationDateValue->setDisabled(true); + return; + } + + const auto modification_date = + QDate(common_info.last_write_date.year, common_info.last_write_date.month, + common_info.last_write_date.day); + ui->modificationDateValue->setDate(modification_date); +} + +void QtAmiiboSettingsDialog::LoadAmiiboGameInfo() { + u32 application_area_id{}; + const auto application_result = nfp_device->GetApplicationAreaId(application_area_id); + + if (application_result.IsFailure()) { + ui->gameIdValue->setVisible(false); + ui->gameIdLabel->setText(tr("No game data present")); + return; + } + + SetGameDataName(application_area_id); +} + +void QtAmiiboSettingsDialog::SetGameDataName(u32 application_area_id) { + static constexpr std::array, 12> game_name_list = { + // 3ds, wii u + std::pair{0x10110E00, "Super Smash Bros (3DS/WiiU)"}, + {0x00132600, "Mario & Luigi: Paper Jam"}, + {0x0014F000, "Animal Crossing: Happy Home Designer"}, + {0x00152600, "Chibi-Robo!: Zip Lash"}, + {0x10161f00, "Mario Party 10"}, + {0x1019C800, "The Legend of Zelda: Twilight Princess HD"}, + // switch + {0x10162B00, "Splatoon 2"}, + {0x1016e100, "Shovel Knight: Treasure Trove"}, + {0x1019C800, "The Legend of Zelda: Breath of the Wild"}, + {0x34F80200, "Super Smash Bros. Ultimate"}, + {0x38600500, "Splatoon 3"}, + {0x3B440400, "The Legend of Zelda: Link's Awakening"}, + }; + + for (const auto& [game_id, game_name] : game_name_list) { + if (application_area_id == game_id) { + ui->gameIdValue->setText(QString::fromStdString(game_name)); + return; + } + } + + const auto application_area_string = fmt::format("{:016x}", application_area_id); + ui->gameIdValue->setText(QString::fromStdString(application_area_string)); +} + +void QtAmiiboSettingsDialog::SetSettingsDescription() { + switch (parameters.mode) { + case Service::NFP::CabinetMode::StartFormatter: + ui->cabinetActionDescriptionLabel->setText( + tr("The following amiibo data will be formatted:")); + break; + case Service::NFP::CabinetMode::StartGameDataEraser: + ui->cabinetActionDescriptionLabel->setText(tr("The following game data will removed:")); + break; + case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: + ui->cabinetActionDescriptionLabel->setText(tr("Set nickname and owner:")); + break; + case Service::NFP::CabinetMode::StartRestorer: + ui->cabinetActionDescriptionLabel->setText(tr("Do you wish to restore this amiibo?")); + break; + } +} + +QtAmiiboSettings::QtAmiiboSettings(GMainWindow& parent) { + connect(this, &QtAmiiboSettings::MainWindowShowAmiiboSettings, &parent, + &GMainWindow::AmiiboSettingsShowDialog, Qt::QueuedConnection); + connect(&parent, &GMainWindow::AmiiboSettingsFinished, this, + &QtAmiiboSettings::MainWindowFinished, Qt::QueuedConnection); +} + +QtAmiiboSettings::~QtAmiiboSettings() = default; + +void QtAmiiboSettings::ShowCabinetApplet( + const Core::Frontend::CabinetCallback& callback_, + const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device) const { + callback = std::move(callback_); + emit MainWindowShowAmiiboSettings(parameters, nfp_device); +} + +void QtAmiiboSettings::MainWindowFinished(bool is_success, const std::string& name) { + callback(is_success, name); +} diff --git a/src/yuzu/applets/qt_amiibo_settings.h b/src/yuzu/applets/qt_amiibo_settings.h new file mode 100644 index 000000000..930c96739 --- /dev/null +++ b/src/yuzu/applets/qt_amiibo_settings.h @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include "core/frontend/applets/cabinet.h" + +class GMainWindow; +class QCheckBox; +class QComboBox; +class QDialogButtonBox; +class QGroupBox; +class QLabel; + +namespace InputCommon { +class InputSubsystem; +} + +namespace Ui { +class QtAmiiboSettingsDialog; +} + +namespace Service::NFP { +class NfpDevice; +} // namespace Service::NFP + +class QtAmiiboSettingsDialog final : public QDialog { + Q_OBJECT + +public: + explicit QtAmiiboSettingsDialog(QWidget* parent, Core::Frontend::CabinetParameters parameters_, + InputCommon::InputSubsystem* input_subsystem_, + std::shared_ptr nfp_device_); + ~QtAmiiboSettingsDialog() override; + + int exec() override; + + std::string GetName() const; + +private: + void LoadInfo(); + void LoadAmiiboInfo(); + void LoadAmiiboApiInfo(std::string_view amiibo_id); + void LoadAmiiboData(); + void LoadAmiiboGameInfo(); + void SetGameDataName(u32 application_area_id); + void SetSettingsDescription(); + + std::unique_ptr ui; + + InputCommon::InputSubsystem* input_subsystem; + std::shared_ptr nfp_device; + + // Parameters sent in from the backend HLE applet. + Core::Frontend::CabinetParameters parameters; + + // If false amiibo settings failed to load + bool is_initalized{}; +}; + +class QtAmiiboSettings final : public QObject, public Core::Frontend::CabinetApplet { + Q_OBJECT + +public: + explicit QtAmiiboSettings(GMainWindow& parent); + ~QtAmiiboSettings() override; + + void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_, + const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device) const override; + +signals: + void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device) const; + +private: + void MainWindowFinished(bool is_success, const std::string& name); + + mutable Core::Frontend::CabinetCallback callback; +}; diff --git a/src/yuzu/applets/qt_amiibo_settings.ui b/src/yuzu/applets/qt_amiibo_settings.ui new file mode 100644 index 000000000..f377a6e61 --- /dev/null +++ b/src/yuzu/applets/qt_amiibo_settings.ui @@ -0,0 +1,494 @@ + + + QtAmiiboSettingsDialog + + + + 0 + 0 + 839 + 500 + + + + Amiibo Settings + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 10 + + + 20 + + + 15 + + + 0 + + + 15 + + + + + + 12 + 75 + true + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 20 + + + 15 + + + 15 + + + + + + 250 + 350 + + + + + 236 + 350 + + + + + + + Qt::AlignCenter + + + + + + + 0 + + + 8 + + + 15 + + + + + Amiibo Info + + + + + + + + Series + + + + + + + + 0 + 0 + + + + true + + + + + + + Type + + + + + + + + 0 + 0 + + + + true + + + + + + + Name + + + + + + + + 0 + 0 + + + + true + + + + + + + + + + + + Amiibo Data + + + + + + + + Custom Name + + + + + + + + 0 + 0 + + + + 10 + + + + + + + Owner + + + + + + + + 0 + 0 + + + + 10 + + + + + + + Creation Date + + + + + + + true + + + + 1970 + 1 + 1 + + + + dd/MM/yyyy + + + + + + + Modification Date + + + + + + + true + + + + 1970 + 1 + 1 + + + + dd/MM/yyyy + + + + + + + + + + + + + 500 + 0 + + + + Game Data + + + + + + Game Id + + + + + + + + 0 + 0 + + + + true + + + + + + + + + + + 500 + 0 + + + + Mount Amiibo + + + + + + ... + + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 60 + 20 + + + + + + + + File Path + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + 15 + + + 15 + + + 8 + + + 20 + + + 8 + + + + + true + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + + + + buttonBox + accepted() + QtAmiiboSettingsDialog + accept() + + + buttonBox + rejected() + QtAmiiboSettingsDialog + reject() + + + diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 27266cae3..33f9237e2 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -15,7 +15,7 @@ #endif // VFS includes must be before glad as they will conflict with Windows file api, which uses defines. -#include "applets/qt_amiibo_manager.h" +#include "applets/qt_amiibo_settings.h" #include "applets/qt_controller.h" #include "applets/qt_error.h" #include "applets/qt_profile_select.h" @@ -577,19 +577,19 @@ void GMainWindow::RegisterMetaTypes() { qRegisterMetaType("Core::SystemResultStatus"); } -void GMainWindow::AmiiboManagerShowDialog(const Core::Frontend::CabinetParameters& parameters, - std::shared_ptr nfp_device) { - QtAmiiboManagerDialog dialog(this, parameters, input_subsystem.get(), nfp_device); +void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device) { + QtAmiiboSettingsDialog dialog(this, parameters, input_subsystem.get(), nfp_device); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint); dialog.setWindowModality(Qt::WindowModal); if (dialog.exec() == QDialog::Rejected) { - emit AmiiboManagerFinished(false, {}); + emit AmiiboSettingsFinished(false, {}); return; } - emit AmiiboManagerFinished(true, dialog.GetName()); + emit AmiiboSettingsFinished(true, dialog.GetName()); } void GMainWindow::ControllerSelectorReconfigureControllers( @@ -1569,7 +1569,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p system->SetFilesystem(vfs); system->SetAppletFrontendSet({ - std::make_unique(*this), // Amiibo Manager + std::make_unique(*this), // Amiibo Settings std::make_unique(*this), // Controller Selector std::make_unique(*this), // Error Display nullptr, // Mii Editor diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 2724ecd52..6a9992d05 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -154,7 +154,7 @@ signals: void UpdateInstallProgress(); - void AmiiboManagerFinished(bool is_success, std::string name); + void AmiiboSettingsFinished(bool is_success, const std::string& name); void ControllerSelectorReconfigureFinished(); @@ -177,8 +177,8 @@ public slots: void OnExecuteProgram(std::size_t program_index); void OnExit(); void OnSaveConfig(); - void AmiiboManagerShowDialog(const Core::Frontend::CabinetParameters& parameters, - std::shared_ptr nfp_device); + void AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters, + std::shared_ptr nfp_device); void ControllerSelectorReconfigureControllers( const Core::Frontend::ControllerParameters& parameters); void SoftwareKeyboardInitialize( -- cgit v1.2.3 From 6fa3faec658893c9fae19116232d24dac08babc7 Mon Sep 17 00:00:00 2001 From: Kyle Kienapfel Date: Fri, 11 Nov 2022 04:12:37 -0800 Subject: Add break for default cases Visual Studio has an option to search all files in a solution, so I did a search in there for "default:" looking for any missing break statements. I've left out default statements that return something, and that throw something, even if via ThrowInvalidType. UNREACHABLE leads towards throw R_THROW macro leads towards a return --- src/yuzu/compatdb.cpp | 1 + src/yuzu/main.cpp | 3 +++ 2 files changed, 4 insertions(+) (limited to 'src/yuzu') diff --git a/src/yuzu/compatdb.cpp b/src/yuzu/compatdb.cpp index f46fff340..e5bc5c448 100644 --- a/src/yuzu/compatdb.cpp +++ b/src/yuzu/compatdb.cpp @@ -63,6 +63,7 @@ void CompatDB::Submit() { break; default: LOG_ERROR(Frontend, "Unexpected page: {}", currentId()); + break; } } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 01a002e4f..3c61899aa 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1953,6 +1953,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target } default: UNIMPLEMENTED(); + break; } const QString qpath = QString::fromStdString(Common::FS::PathToUTF8String(path)); @@ -3182,6 +3183,7 @@ void GMainWindow::OnToggleGpuAccuracy() { case Settings::GPUAccuracy::Extreme: default: { Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::High); + break; } } @@ -3514,6 +3516,7 @@ void GMainWindow::UpdateGPUAccuracyButton() { default: { gpu_accuracy_button->setText(tr("GPU ERROR")); gpu_accuracy_button->setChecked(true); + break; } } } -- cgit v1.2.3 From ef5184cf1cddffbd5f10657e3e6bf7c957ddd628 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Tue, 15 Nov 2022 17:57:01 -0500 Subject: configure_profile_manager: Use a custom dialog for deletion A hopefully more informative dialog that most importantly notifies the user that their saves will be deleted with the user profile. cpm: Only keep track of UI elements that we need cpm: Remove unused forward declarations cpm: Add missing include --- .../configuration/configure_profile_manager.cpp | 67 ++++++++++++++++++---- src/yuzu/configuration/configure_profile_manager.h | 25 +++++++- 2 files changed, 81 insertions(+), 11 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 5c0217ba8..9493cb82e 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -2,6 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include +#include +#include #include #include #include @@ -108,9 +111,12 @@ ConfigureProfileManager::ConfigureProfileManager(const Core::System& system_, QW connect(ui->pm_add, &QPushButton::clicked, this, &ConfigureProfileManager::AddUser); connect(ui->pm_rename, &QPushButton::clicked, this, &ConfigureProfileManager::RenameUser); - connect(ui->pm_remove, &QPushButton::clicked, this, &ConfigureProfileManager::DeleteUser); + connect(ui->pm_remove, &QPushButton::clicked, this, + &ConfigureProfileManager::ConfirmDeleteUser); connect(ui->pm_set_image, &QPushButton::clicked, this, &ConfigureProfileManager::SetUserImage); + confirm_dialog = std::make_unique(this); + scene = new QGraphicsScene; ui->current_user_icon->setScene(scene); @@ -230,26 +236,23 @@ void ConfigureProfileManager::RenameUser() { UpdateCurrentUser(); } -void ConfigureProfileManager::DeleteUser() { +void ConfigureProfileManager::ConfirmDeleteUser() { const auto index = tree_view->currentIndex().row(); const auto uuid = profile_manager->GetUser(index); ASSERT(uuid); const auto username = GetAccountUsername(*profile_manager, *uuid); - const auto confirm = QMessageBox::question( - this, tr("Confirm Delete"), - tr("You are about to delete user with name \"%1\". Are you sure?").arg(username)); - - if (confirm == QMessageBox::No) { - return; - } + confirm_dialog->SetInfo(username, *uuid, [this, uuid]() { DeleteUser(*uuid); }); + confirm_dialog->show(); +} +void ConfigureProfileManager::DeleteUser(const Common::UUID uuid) { if (Settings::values.current_user.GetValue() == tree_view->currentIndex().row()) { Settings::values.current_user = 0; } UpdateCurrentUser(); - if (!profile_manager->RemoveUser(*uuid)) { + if (!profile_manager->RemoveUser(uuid)) { return; } @@ -319,3 +322,47 @@ void ConfigureProfileManager::SetUserImage() { new QStandardItem{GetIcon(*uuid), FormatUserEntryText(username, *uuid)}); UpdateCurrentUser(); } + +ConfigureProfileManagerDeleteDialog::ConfigureProfileManagerDeleteDialog(QWidget* parent) + : QDialog(parent) { + auto dialog_vbox_layout = new QVBoxLayout(this); + dialog_button_box = + new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::No, Qt::Horizontal, parent); + auto label_message = + new QLabel(tr("Delete this user? All of the user's save data will be deleted."), this); + label_info = new QLabel(this); + auto dialog_hbox_layout_widget = new QWidget(this); + auto dialog_hbox_layout = new QHBoxLayout(dialog_hbox_layout_widget); + icon_scene = new QGraphicsScene(0, 0, 64, 64, this); + auto icon_view = new QGraphicsView(icon_scene, this); + + dialog_hbox_layout_widget->setLayout(dialog_hbox_layout); + icon_view->setMaximumSize(64, 64); + icon_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + icon_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + this->setLayout(dialog_vbox_layout); + this->setWindowTitle(tr("Confirm Delete")); + this->setSizeGripEnabled(false); + dialog_vbox_layout->addWidget(label_message); + dialog_vbox_layout->addWidget(dialog_hbox_layout_widget); + dialog_vbox_layout->addWidget(dialog_button_box); + dialog_hbox_layout->addWidget(icon_view); + dialog_hbox_layout->addWidget(label_info); + + connect(dialog_button_box, &QDialogButtonBox::rejected, this, [this]() { close(); }); +} + +ConfigureProfileManagerDeleteDialog::~ConfigureProfileManagerDeleteDialog() = default; + +void ConfigureProfileManagerDeleteDialog::SetInfo(const QString username, const Common::UUID uuid, + std::function accept_callback) { + label_info->setText( + tr("Name: %1\nUUID: %2").arg(username, QString::fromStdString(uuid.FormattedString()))); + icon_scene->clear(); + icon_scene->addPixmap(GetIcon(uuid)); + + connect(dialog_button_box, &QDialogButtonBox::accepted, this, [this, accept_callback]() { + close(); + accept_callback(); + }); +} diff --git a/src/yuzu/configuration/configure_profile_manager.h b/src/yuzu/configuration/configure_profile_manager.h index fe9033779..6e5cb748d 100644 --- a/src/yuzu/configuration/configure_profile_manager.h +++ b/src/yuzu/configuration/configure_profile_manager.h @@ -3,16 +3,22 @@ #pragma once +#include #include +#include #include #include +#include "common/uuid.h" + namespace Core { class System; } class QGraphicsScene; +class QDialogButtonBox; +class QLabel; class QStandardItem; class QStandardItemModel; class QTreeView; @@ -26,6 +32,20 @@ namespace Ui { class ConfigureProfileManager; } +class ConfigureProfileManagerDeleteDialog : public QDialog { +public: + explicit ConfigureProfileManagerDeleteDialog(QWidget* parent); + ~ConfigureProfileManagerDeleteDialog(); + + void SetInfo(const QString username, const Common::UUID uuid, + std::function accept_callback); + +private: + QDialogButtonBox* dialog_button_box; + QGraphicsScene* icon_scene; + QLabel* label_info; +}; + class ConfigureProfileManager : public QWidget { Q_OBJECT @@ -47,7 +67,8 @@ private: void SelectUser(const QModelIndex& index); void AddUser(); void RenameUser(); - void DeleteUser(); + void ConfirmDeleteUser(); + void DeleteUser(const Common::UUID uuid); void SetUserImage(); QVBoxLayout* layout; @@ -55,6 +76,8 @@ private: QStandardItemModel* item_model; QGraphicsScene* scene; + std::unique_ptr confirm_dialog; + std::vector> list_items; std::unique_ptr ui; -- cgit v1.2.3 From 8ca02794c5723d0b678610b3a1a90bba9e703bb0 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Tue, 15 Nov 2022 17:58:06 -0500 Subject: configure_profile_manager: Remove profile picture border The border adds its own width at least on Linux which causes the icon to be offset by 1px, and cropped by 2px on the bottom and right sides. --- src/yuzu/configuration/configure_profile_manager.ui | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/configure_profile_manager.ui b/src/yuzu/configuration/configure_profile_manager.ui index cfe7478c8..bd6dea4f4 100644 --- a/src/yuzu/configuration/configure_profile_manager.ui +++ b/src/yuzu/configuration/configure_profile_manager.ui @@ -57,6 +57,12 @@ 48 + + QFrame::NoFrame + + + QFrame::Plain + Qt::ScrollBarAlwaysOff -- cgit v1.2.3 From e94bcf03cb20d65b6bda65fccb3f259783c8ff86 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Tue, 15 Nov 2022 19:25:09 -0500 Subject: configure_profile_manager: Cleanup reference/pointer usage Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com> Co-authored-by: Mai M. --- src/yuzu/configuration/configure_profile_manager.cpp | 8 ++++---- src/yuzu/configuration/configure_profile_manager.h | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 9493cb82e..a47089988 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -115,7 +115,7 @@ ConfigureProfileManager::ConfigureProfileManager(const Core::System& system_, QW &ConfigureProfileManager::ConfirmDeleteUser); connect(ui->pm_set_image, &QPushButton::clicked, this, &ConfigureProfileManager::SetUserImage); - confirm_dialog = std::make_unique(this); + confirm_dialog = new ConfigureProfileManagerDeleteDialog(this); scene = new QGraphicsScene; ui->current_user_icon->setScene(scene); @@ -246,7 +246,7 @@ void ConfigureProfileManager::ConfirmDeleteUser() { confirm_dialog->show(); } -void ConfigureProfileManager::DeleteUser(const Common::UUID uuid) { +void ConfigureProfileManager::DeleteUser(const Common::UUID& uuid) { if (Settings::values.current_user.GetValue() == tree_view->currentIndex().row()) { Settings::values.current_user = 0; } @@ -324,7 +324,7 @@ void ConfigureProfileManager::SetUserImage() { } ConfigureProfileManagerDeleteDialog::ConfigureProfileManagerDeleteDialog(QWidget* parent) - : QDialog(parent) { + : QDialog{parent} { auto dialog_vbox_layout = new QVBoxLayout(this); dialog_button_box = new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::No, Qt::Horizontal, parent); @@ -354,7 +354,7 @@ ConfigureProfileManagerDeleteDialog::ConfigureProfileManagerDeleteDialog(QWidget ConfigureProfileManagerDeleteDialog::~ConfigureProfileManagerDeleteDialog() = default; -void ConfigureProfileManagerDeleteDialog::SetInfo(const QString username, const Common::UUID uuid, +void ConfigureProfileManagerDeleteDialog::SetInfo(const QString& username, const Common::UUID& uuid, std::function accept_callback) { label_info->setText( tr("Name: %1\nUUID: %2").arg(username, QString::fromStdString(uuid.FormattedString()))); diff --git a/src/yuzu/configuration/configure_profile_manager.h b/src/yuzu/configuration/configure_profile_manager.h index 6e5cb748d..c4b1a334e 100644 --- a/src/yuzu/configuration/configure_profile_manager.h +++ b/src/yuzu/configuration/configure_profile_manager.h @@ -10,7 +10,9 @@ #include #include -#include "common/uuid.h" +namespace Common { +struct UUID; +} namespace Core { class System; @@ -37,7 +39,7 @@ public: explicit ConfigureProfileManagerDeleteDialog(QWidget* parent); ~ConfigureProfileManagerDeleteDialog(); - void SetInfo(const QString username, const Common::UUID uuid, + void SetInfo(const QString& username, const Common::UUID& uuid, std::function accept_callback); private: @@ -68,7 +70,7 @@ private: void AddUser(); void RenameUser(); void ConfirmDeleteUser(); - void DeleteUser(const Common::UUID uuid); + void DeleteUser(const Common::UUID& uuid); void SetUserImage(); QVBoxLayout* layout; @@ -76,7 +78,7 @@ private: QStandardItemModel* item_model; QGraphicsScene* scene; - std::unique_ptr confirm_dialog; + ConfigureProfileManagerDeleteDialog* confirm_dialog; std::vector> list_items; -- cgit v1.2.3