diff options
| -rw-r--r-- | src/yuzu/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/yuzu/applets/qt_amiibo_manager.cpp | 247 | ||||
| -rw-r--r-- | src/yuzu/applets/qt_amiibo_manager.h | 93 | ||||
| -rw-r--r-- | src/yuzu/applets/qt_amiibo_manager.ui | 491 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 23 | ||||
| -rw-r--r-- | src/yuzu/main.h | 9 | 
6 files changed, 865 insertions, 1 deletions
| 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 <algorithm> +#include <thread> +#include <fmt/format.h> +#include <nlohmann/json.hpp> + +#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<Service::NFP::NfpDevice> nfp_device_) +    : QDialog(parent), ui(std::make_unique<Ui::QtAmiiboManagerDialog>()), +      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<const u8*>(image_data.data()), +                        static_cast<uint>(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<std::pair<u32, QString>, 12> game_name_list = { +        // 3ds, wii u +        std::pair<u32, QString>{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<void(bool, const std::string&)> callback_, +                                        const Core::Frontend::CabinetParameters& parameters, +                                        std::shared_ptr<Service::NFP::NfpDevice> 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 <array> +#include <memory> +#include <QDialog> +#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<Service::NFP::NfpDevice> 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::QtAmiiboManagerDialog> ui; + +    InputCommon::InputSubsystem* input_subsystem; +    std::shared_ptr<Service::NFP::NfpDevice> 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<void(bool, const std::string&)> callback_, +                           const Core::Frontend::CabinetParameters& parameters, +                           std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override; + +signals: +    void MainWindowShowAmiiboManager(const Core::Frontend::CabinetParameters& parameters, +                                     std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const; + +private: +    void MainWindowFinished(bool is_success, std::string name); + +    mutable std::function<void(bool, const std::string&)> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtAmiiboManagerDialog</class> + <widget class="QDialog" name="QtAmiiboManagerDialog"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>839</width> +    <height>500</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>Amiibo Manager</string> +  </property> +  <property name="styleSheet"> +   <string notr="true"/> +  </property> +  <layout class="QVBoxLayout" name="verticalLayout" stretch="0"> +   <property name="leftMargin"> +    <number>0</number> +   </property> +   <property name="topMargin"> +    <number>0</number> +   </property> +   <property name="rightMargin"> +    <number>0</number> +   </property> +   <property name="bottomMargin"> +    <number>0</number> +   </property> +   <item> +    <widget class="QWidget" name="mainControllerApplet" native="true"> +     <layout class="QVBoxLayout" name="verticalLayout_1" stretch="0,3,0"> +      <property name="spacing"> +       <number>0</number> +      </property> +      <property name="leftMargin"> +       <number>0</number> +      </property> +      <property name="topMargin"> +       <number>0</number> +      </property> +      <property name="rightMargin"> +       <number>0</number> +      </property> +      <property name="bottomMargin"> +       <number>0</number> +      </property> +      <item> +       <widget class="QWidget" name="topControllerApplet" native="true"> +        <layout class="QHBoxLayout" name="horizontalLayout"> +         <property name="spacing"> +          <number>10</number> +         </property> +         <property name="leftMargin"> +          <number>20</number> +         </property> +         <property name="topMargin"> +          <number>15</number> +         </property> +         <property name="rightMargin"> +          <number>0</number> +         </property> +         <property name="bottomMargin"> +          <number>15</number> +         </property> +         <item> +          <widget class="QLabel" name="cabinetActionDescriptionLabel"> +           <property name="font"> +            <font> +             <pointsize>12</pointsize> +             <weight>75</weight> +             <bold>true</bold> +            </font> +           </property> +           <property name="text"> +            <string/> +           </property> +           <property name="alignment"> +            <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> +           </property> +           <property name="wordWrap"> +            <bool>false</bool> +           </property> +          </widget> +         </item> +         <item> +          <spacer name="horizontalSpacer_2"> +           <property name="orientation"> +            <enum>Qt::Horizontal</enum> +           </property> +           <property name="sizeHint" stdset="0"> +            <size> +             <width>40</width> +             <height>20</height> +            </size> +           </property> +          </spacer> +         </item> +        </layout> +       </widget> +      </item> +      <item> +       <widget class="QWidget" name="middleControllerApplet" native="true"> +        <layout class="QVBoxLayout" name="verticalLayout_3"> +         <property name="spacing"> +          <number>0</number> +         </property> +         <property name="leftMargin"> +          <number>0</number> +         </property> +         <property name="topMargin"> +          <number>0</number> +         </property> +         <property name="rightMargin"> +          <number>0</number> +         </property> +         <property name="bottomMargin"> +          <number>0</number> +         </property> +         <item> +          <layout class="QHBoxLayout" name="horizontalLayout_2"> +           <property name="leftMargin"> +            <number>20</number> +           </property> +           <property name="rightMargin"> +            <number>15</number> +           </property> +           <item> +            <widget class="QLabel" name="amiiboImageLabel"> +             <property name="minimumSize"> +              <size> +               <width>250</width> +               <height>350</height> +              </size> +             </property> +             <property name="maximumSize"> +              <size> +               <width>236</width> +               <height>350</height> +              </size> +             </property> +             <property name="text"> +              <string/> +             </property> +             <property name="alignment"> +              <set>Qt::AlignCenter</set> +             </property> +            </widget> +           </item> +           <item> +            <layout class="QVBoxLayout" name="verticalLayout_4"> +             <property name="leftMargin"> +              <number>20</number> +             </property> +             <property name="topMargin"> +              <number>8</number> +             </property> +             <property name="bottomMargin"> +              <number>15</number> +             </property> +             <item> +              <widget class="QGroupBox" name="amiiboInfoGroup"> +               <property name="title"> +                <string>Amiibo Info</string> +               </property> +               <layout class="QVBoxLayout" name="verticalLayout_5"> +                <item> +                 <layout class="QGridLayout" name="gridLayout_1"> +                  <item row="0" column="0"> +                   <widget class="QLabel" name="amiiboSeriesLabel"> +                    <property name="text"> +                     <string>Series</string> +                    </property> +                   </widget> +                  </item> +                  <item row="0" column="1"> +                   <widget class="QLineEdit" name="amiiboSeriesValue"> +                    <property name="sizePolicy"> +                     <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> +                      <horstretch>0</horstretch> +                      <verstretch>0</verstretch> +                     </sizepolicy> +                    </property> +                    <property name="readOnly"> +                     <bool>true</bool> +                    </property> +                   </widget> +                  </item> +                  <item row="1" column="0"> +                   <widget class="QLabel" name="amiiboTypeLabel"> +                    <property name="text"> +                     <string>Type</string> +                    </property> +                   </widget> +                  </item> +                  <item row="1" column="1"> +                   <widget class="QLineEdit" name="amiiboTypeValue"> +                    <property name="sizePolicy"> +                     <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> +                      <horstretch>0</horstretch> +                      <verstretch>0</verstretch> +                     </sizepolicy> +                    </property> +                    <property name="readOnly"> +                     <bool>true</bool> +                    </property> +                   </widget> +                  </item> +                  <item row="2" column="0"> +                   <widget class="QLabel" name="amiiboNameLabel"> +                    <property name="text"> +                     <string>Name</string> +                    </property> +                   </widget> +                  </item> +                  <item row="2" column="1"> +                   <widget class="QLineEdit" name="amiiboNameValue"> +                    <property name="sizePolicy"> +                     <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> +                      <horstretch>0</horstretch> +                      <verstretch>0</verstretch> +                     </sizepolicy> +                    </property> +                    <property name="readOnly"> +                     <bool>true</bool> +                    </property> +                   </widget> +                  </item> +                 </layout> +                </item> +               </layout> +              </widget> +             </item> +             <item> +              <widget class="QGroupBox" name="amiiboDataGroup"> +               <property name="title"> +                <string>Amiibo Data</string> +               </property> +               <layout class="QVBoxLayout" name="verticalLayout_6"> +                <item> +                 <layout class="QGridLayout" name="gridLayout_2"> +                  <item row="0" column="0"> +                   <widget class="QLabel" name="amiiboCustomNameLabel"> +                    <property name="text"> +                     <string>Custom Name</string> +                    </property> +                   </widget> +                  </item> +                  <item row="0" column="1"> +                   <widget class="QLineEdit" name="amiiboCustomNameValue"> +                    <property name="sizePolicy"> +                     <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> +                      <horstretch>0</horstretch> +                      <verstretch>0</verstretch> +                     </sizepolicy> +                    </property> +                    <property name="maxLength"> +                     <number>10</number> +                    </property> +                   </widget> +                  </item> +                  <item row="1" column="0"> +                   <widget class="QLabel" name="amiiboOwnerLabel"> +                    <property name="text"> +                     <string>Owner</string> +                    </property> +                   </widget> +                  </item> +                  <item row="1" column="1"> +                   <widget class="QLineEdit" name="amiiboOwnerValue"> +                    <property name="sizePolicy"> +                     <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> +                      <horstretch>0</horstretch> +                      <verstretch>0</verstretch> +                     </sizepolicy> +                    </property> +                    <property name="maxLength"> +                     <number>10</number> +                    </property> +                   </widget> +                  </item> +                  <item row="2" column="0"> +                   <widget class="QLabel" name="creationDateLabel"> +                    <property name="text"> +                     <string>Creation Date</string> +                    </property> +                   </widget> +                  </item> +                  <item row="2" column="1"> +                   <widget class="QDateTimeEdit" name="creationDateValue"> +                    <property name="readOnly"> +                     <bool>true</bool> +                    </property> +                    <property name="minimumDate"> +                     <date> +                      <year>1970</year> +                      <month>1</month> +                      <day>1</day> +                     </date> +                    </property> +                    <property name="displayFormat"> +                     <string>dd/MM/yyyy</string> +                    </property> +                   </widget> +                  </item> +                  <item row="3" column="0"> +                   <widget class="QLabel" name="modificationDateLabel"> +                    <property name="text"> +                     <string>Modification Date</string> +                    </property> +                   </widget> +                  </item> +                  <item row="3" column="1"> +                   <widget class="QDateTimeEdit" name="modificationDateValue"> +                    <property name="readOnly"> +                     <bool>true</bool> +                    </property> +                    <property name="minimumDate"> +                     <date> +                      <year>1970</year> +                      <month>1</month> +                      <day>1</day> +                     </date> +                    </property> +                    <property name="displayFormat"> +                     <string>dd/MM/yyyy </string> +                    </property> +                   </widget> +                  </item> +                 </layout> +                </item> +               </layout> +              </widget> +             </item> +             <item> +              <widget class="QGroupBox" name="gameDataGroup"> +               <property name="minimumSize"> +                <size> +                 <width>500</width> +                 <height>0</height> +                </size> +               </property> +               <property name="title"> +                <string>Game Data</string> +               </property> +               <layout class="QGridLayout" name="gridLayout_3"> +                <item row="0" column="0"> +                 <widget class="QLabel" name="gameIdLabel"> +                  <property name="text"> +                   <string>Game Id</string> +                  </property> +                 </widget> +                </item> +                <item row="0" column="1"> +                 <widget class="QLineEdit" name="gameIdValue"> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="readOnly"> +                   <bool>true</bool> +                  </property> +                 </widget> +                </item> +               </layout> +              </widget> +             </item> +             <item> +              <widget class="QGroupBox" name="MountAmiiboGroup"> +               <property name="minimumSize"> +                <size> +                 <width>500</width> +                 <height>0</height> +                </size> +               </property> +               <property name="title"> +                <string>Mount Amiibo</string> +               </property> +               <layout class="QGridLayout" name="gridLayout_4"> +                <item row="0" column="3"> +                 <widget class="QToolButton" name="amiiboDirectoryButton"> +                  <property name="text"> +                   <string>...</string> +                  </property> +                 </widget> +                </item> +                <item row="0" column="1"> +                 <spacer name="horizontalSpacer"> +                  <property name="orientation"> +                   <enum>Qt::Horizontal</enum> +                  </property> +                  <property name="sizeType"> +                   <enum>QSizePolicy::Maximum</enum> +                  </property> +                  <property name="sizeHint" stdset="0"> +                   <size> +                    <width>60</width> +                    <height>20</height> +                   </size> +                  </property> +                 </spacer> +                </item> +                <item row="0" column="0"> +                 <widget class="QLabel" name="amiiboDirectoryLabel"> +                  <property name="text"> +                   <string>File Path</string> +                  </property> +                 </widget> +                </item> +                <item row="0" column="2"> +                 <widget class="QLineEdit" name="amiiboDirectoryValue"/> +                </item> +               </layout> +              </widget> +             </item> +             <item> +              <spacer name="verticalSpacer"> +               <property name="orientation"> +                <enum>Qt::Vertical</enum> +               </property> +               <property name="sizeHint" stdset="0"> +                <size> +                 <width>20</width> +                 <height>40</height> +                </size> +               </property> +              </spacer> +             </item> +            </layout> +           </item> +          </layout> +         </item> +        </layout> +       </widget> +      </item> +      <item> +       <widget class="QWidget" name="bottomControllerApplet" native="true"> +        <layout class="QHBoxLayout" name="horizontalLayout_6"> +         <property name="spacing"> +          <number>15</number> +         </property> +         <property name="leftMargin"> +          <number>15</number> +         </property> +         <property name="topMargin"> +          <number>8</number> +         </property> +         <property name="rightMargin"> +          <number>20</number> +         </property> +         <property name="bottomMargin"> +          <number>8</number> +         </property> +         <item alignment="Qt::AlignBottom"> +          <widget class="QDialogButtonBox" name="buttonBox"> +           <property name="enabled"> +            <bool>true</bool> +           </property> +           <property name="standardButtons"> +            <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> +           </property> +          </widget> +         </item> +        </layout> +       </widget> +      </item> +     </layout> +    </widget> +   </item> +  </layout> + </widget> + <resources/> + <connections> +  <connection> +   <sender>buttonBox</sender> +   <signal>accepted()</signal> +   <receiver>QtAmiiboManagerDialog</receiver> +   <slot>accept()</slot> +  </connection> +  <connection> +   <sender>buttonBox</sender> +   <signal>rejected()</signal> +   <receiver>QtAmiiboManagerDialog</receiver> +   <slot>reject()</slot> +  </connection> + </connections> +</ui> 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>("Core::Frontend::CabinetParameters"); +    qRegisterMetaType<std::shared_ptr<Service::NFP::NfpDevice>>( +        "std::shared_ptr<Service::NFP::NfpDevice>"); +      // Controller Applet      qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters"); @@ -571,6 +577,21 @@ void GMainWindow::RegisterMetaTypes() {      qRegisterMetaType<Core::SystemResultStatus>("Core::SystemResultStatus");  } +void GMainWindow::AmiiboManagerShowDialog(const Core::Frontend::CabinetParameters& parameters, +                                          std::shared_ptr<Service::NFP::NfpDevice> 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<QtAmiiboManager>(*this),      // Amiibo Manager          std::make_unique<QtControllerSelector>(*this), // Controller Selector          std::make_unique<QtErrorDisplay>(*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<Service::NFP::NfpDevice> nfp_device);      void ControllerSelectorReconfigureControllers(          const Core::Frontend::ControllerParameters& parameters);      void SoftwareKeyboardInitialize( | 
