Merge branch 'master' of https://github.com/dolphin-emu/dolphin into dolphin-emu-master

This commit is contained in:
Nayla Hanegan 2023-06-23 12:58:43 -04:00
commit 6280ce45a7
No known key found for this signature in database
GPG key ID: 3075216CED0DB01D
415 changed files with 14795 additions and 9405 deletions

View file

@ -0,0 +1,239 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef USE_RETRO_ACHIEVEMENTS
#include "DolphinQt/Achievements/AchievementSettingsWidget.h"
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
#include <QVBoxLayout>
#include "Core/AchievementManager.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
#include "DolphinQt/Achievements/AchievementsWindow.h"
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
static constexpr bool hardcore_mode_enabled = false;
AchievementSettingsWidget::AchievementSettingsWidget(QWidget* parent,
AchievementsWindow* parent_window)
: QWidget(parent), parent_window(parent_window)
{
CreateLayout();
LoadSettings();
ConnectWidgets();
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
&AchievementSettingsWidget::LoadSettings);
}
void AchievementSettingsWidget::CreateLayout()
{
m_common_layout = new QVBoxLayout();
m_common_integration_enabled_input =
new ToolTipCheckBox(tr("Enable RetroAchievements.org Integration"));
m_common_integration_enabled_input->SetDescription(
tr("Enable integration with RetroAchievements for earning achievements and competing in "
"leaderboards.<br><br>Must log in with a RetroAchievements account to use. Dolphin does "
"not save your password locally and uses an API token to maintain login."));
m_common_username_label = new QLabel(tr("Username"));
m_common_username_input = new QLineEdit(QStringLiteral(""));
m_common_password_label = new QLabel(tr("Password"));
m_common_password_input = new QLineEdit(QStringLiteral(""));
m_common_password_input->setEchoMode(QLineEdit::Password);
m_common_login_button = new QPushButton(tr("Login"));
m_common_logout_button = new QPushButton(tr("Logout"));
m_common_login_failed = new QLabel(tr("Login Failed"));
m_common_login_failed->setStyleSheet(QStringLiteral("QLabel { color : red; }"));
m_common_login_failed->setVisible(false);
m_common_achievements_enabled_input = new ToolTipCheckBox(tr("Enable Achievements"));
m_common_achievements_enabled_input->SetDescription(tr("Enable unlocking achievements.<br>"));
m_common_leaderboards_enabled_input = new ToolTipCheckBox(tr("Enable Leaderboards"));
m_common_leaderboards_enabled_input->SetDescription(
tr("Enable competing in RetroAchievements leaderboards.<br><br>Hardcore Mode must be enabled "
"to use."));
m_common_rich_presence_enabled_input = new ToolTipCheckBox(tr("Enable Rich Presence"));
m_common_rich_presence_enabled_input->SetDescription(
tr("Enable detailed rich presence on the RetroAchievements website.<br><br>This provides a "
"detailed description of what the player is doing in game to the website. If this is "
"disabled, the website will only report what game is being played.<br><br>This has no "
"bearing on Discord rich presence."));
m_common_unofficial_enabled_input = new ToolTipCheckBox(tr("Enable Unofficial Achievements"));
m_common_unofficial_enabled_input->SetDescription(
tr("Enable unlocking unofficial achievements as well as official "
"achievements.<br><br>Unofficial achievements may be optional or unfinished achievements "
"that have not been deemed official by RetroAchievements and may be useful for testing or "
"simply for fun."));
m_common_encore_enabled_input = new ToolTipCheckBox(tr("Enable Encore Achievements"));
m_common_encore_enabled_input->SetDescription(tr(
"Enable unlocking achievements in Encore Mode.<br><br>Encore Mode re-enables achievements "
"the player has already unlocked on the site so that the player will be notified if they "
"meet the unlock conditions again, useful for custom speedrun criteria or simply for fun."));
m_common_layout->addWidget(m_common_integration_enabled_input);
m_common_layout->addWidget(m_common_username_label);
m_common_layout->addWidget(m_common_username_input);
m_common_layout->addWidget(m_common_password_label);
m_common_layout->addWidget(m_common_password_input);
m_common_layout->addWidget(m_common_login_button);
m_common_layout->addWidget(m_common_logout_button);
m_common_layout->addWidget(m_common_login_failed);
m_common_layout->addWidget(m_common_achievements_enabled_input);
m_common_layout->addWidget(m_common_leaderboards_enabled_input);
m_common_layout->addWidget(m_common_rich_presence_enabled_input);
m_common_layout->addWidget(m_common_unofficial_enabled_input);
m_common_layout->addWidget(m_common_encore_enabled_input);
m_common_layout->setAlignment(Qt::AlignTop);
setLayout(m_common_layout);
}
void AchievementSettingsWidget::ConnectWidgets()
{
connect(m_common_integration_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleRAIntegration);
connect(m_common_login_button, &QPushButton::pressed, this, &AchievementSettingsWidget::Login);
connect(m_common_logout_button, &QPushButton::pressed, this, &AchievementSettingsWidget::Logout);
connect(m_common_achievements_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleAchievements);
connect(m_common_leaderboards_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleLeaderboards);
connect(m_common_rich_presence_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleRichPresence);
connect(m_common_unofficial_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleUnofficial);
connect(m_common_encore_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleEncore);
}
void AchievementSettingsWidget::OnControllerInterfaceConfigure()
{
ControllerInterfaceWindow* window = new ControllerInterfaceWindow(this);
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
window->show();
}
void AchievementSettingsWidget::LoadSettings()
{
bool enabled = Config::Get(Config::RA_ENABLED);
bool achievements_enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED);
bool logged_out = Config::Get(Config::RA_API_TOKEN).empty();
std::string username = Config::Get(Config::RA_USERNAME);
SignalBlocking(m_common_integration_enabled_input)->setChecked(enabled);
SignalBlocking(m_common_username_label)->setEnabled(enabled);
if (!username.empty())
SignalBlocking(m_common_username_input)->setText(QString::fromStdString(username));
SignalBlocking(m_common_username_input)->setEnabled(enabled && logged_out);
SignalBlocking(m_common_password_label)->setVisible(logged_out);
SignalBlocking(m_common_password_label)->setEnabled(enabled);
SignalBlocking(m_common_password_input)->setVisible(logged_out);
SignalBlocking(m_common_password_input)->setEnabled(enabled);
SignalBlocking(m_common_login_button)->setVisible(logged_out);
SignalBlocking(m_common_login_button)->setEnabled(enabled && !Core::IsRunning());
SignalBlocking(m_common_logout_button)->setVisible(!logged_out);
SignalBlocking(m_common_logout_button)->setEnabled(enabled);
SignalBlocking(m_common_achievements_enabled_input)->setChecked(achievements_enabled);
SignalBlocking(m_common_achievements_enabled_input)->setEnabled(enabled);
SignalBlocking(m_common_leaderboards_enabled_input)
->setChecked(Config::Get(Config::RA_LEADERBOARDS_ENABLED));
SignalBlocking(m_common_leaderboards_enabled_input)->setEnabled(enabled && hardcore_mode_enabled);
SignalBlocking(m_common_rich_presence_enabled_input)
->setChecked(Config::Get(Config::RA_RICH_PRESENCE_ENABLED));
SignalBlocking(m_common_rich_presence_enabled_input)->setEnabled(enabled);
SignalBlocking(m_common_unofficial_enabled_input)
->setChecked(Config::Get(Config::RA_UNOFFICIAL_ENABLED));
SignalBlocking(m_common_unofficial_enabled_input)->setEnabled(enabled && achievements_enabled);
SignalBlocking(m_common_encore_enabled_input)->setChecked(Config::Get(Config::RA_ENCORE_ENABLED));
SignalBlocking(m_common_encore_enabled_input)->setEnabled(enabled && achievements_enabled);
}
void AchievementSettingsWidget::SaveSettings()
{
Config::ConfigChangeCallbackGuard config_guard;
Config::SetBaseOrCurrent(Config::RA_ENABLED, m_common_integration_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_ACHIEVEMENTS_ENABLED,
m_common_achievements_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_LEADERBOARDS_ENABLED,
m_common_leaderboards_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_RICH_PRESENCE_ENABLED,
m_common_rich_presence_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_UNOFFICIAL_ENABLED,
m_common_unofficial_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_ENCORE_ENABLED, m_common_encore_enabled_input->isChecked());
Config::Save();
}
void AchievementSettingsWidget::ToggleRAIntegration()
{
SaveSettings();
if (Config::Get(Config::RA_ENABLED))
AchievementManager::GetInstance()->Init();
else
AchievementManager::GetInstance()->Shutdown();
}
void AchievementSettingsWidget::Login()
{
Config::SetBaseOrCurrent(Config::RA_USERNAME, m_common_username_input->text().toStdString());
AchievementManager::GetInstance()->Login(m_common_password_input->text().toStdString());
m_common_password_input->setText(QString());
m_common_login_failed->setVisible(Config::Get(Config::RA_API_TOKEN).empty());
SaveSettings();
}
void AchievementSettingsWidget::Logout()
{
AchievementManager::GetInstance()->Logout();
SaveSettings();
}
void AchievementSettingsWidget::ToggleAchievements()
{
SaveSettings();
AchievementManager::GetInstance()->ActivateDeactivateAchievements();
}
void AchievementSettingsWidget::ToggleLeaderboards()
{
SaveSettings();
AchievementManager::GetInstance()->ActivateDeactivateLeaderboards();
}
void AchievementSettingsWidget::ToggleRichPresence()
{
SaveSettings();
AchievementManager::GetInstance()->ActivateDeactivateRichPresence();
}
void AchievementSettingsWidget::ToggleUnofficial()
{
SaveSettings();
AchievementManager::GetInstance()->ActivateDeactivateAchievements();
}
void AchievementSettingsWidget::ToggleEncore()
{
SaveSettings();
AchievementManager::GetInstance()->ActivateDeactivateAchievements();
}
#endif // USE_RETRO_ACHIEVEMENTS

View file

@ -0,0 +1,62 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#ifdef USE_RETRO_ACHIEVEMENTS
#include <QWidget>
class AchievementsWindow;
class QGroupBox;
class QVBoxLayout;
class QLabel;
class QLineEdit;
class QPushButton;
class ToolTipCheckBox;
class AchievementSettingsWidget final : public QWidget
{
Q_OBJECT
public:
explicit AchievementSettingsWidget(QWidget* parent, AchievementsWindow* parent_window);
private:
void OnControllerInterfaceConfigure();
void CreateLayout();
void ConnectWidgets();
void LoadSettings();
void SaveSettings();
void ToggleRAIntegration();
void Login();
void Logout();
void ToggleAchievements();
void ToggleLeaderboards();
void ToggleRichPresence();
void ToggleHardcore();
void ToggleBadgeIcons();
void ToggleUnofficial();
void ToggleEncore();
AchievementsWindow* parent_window;
QGroupBox* m_common_box;
QVBoxLayout* m_common_layout;
ToolTipCheckBox* m_common_integration_enabled_input;
QLabel* m_common_login_failed;
QLabel* m_common_username_label;
QLineEdit* m_common_username_input;
QLabel* m_common_password_label;
QLineEdit* m_common_password_input;
QPushButton* m_common_login_button;
QPushButton* m_common_logout_button;
ToolTipCheckBox* m_common_achievements_enabled_input;
ToolTipCheckBox* m_common_leaderboards_enabled_input;
ToolTipCheckBox* m_common_rich_presence_enabled_input;
ToolTipCheckBox* m_common_unofficial_enabled_input;
ToolTipCheckBox* m_common_encore_enabled_input;
};
#endif // USE_RETRO_ACHIEVEMENTS

View file

@ -0,0 +1,56 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef USE_RETRO_ACHIEVEMENTS
#include "DolphinQt/Achievements/AchievementsWindow.h"
#include <QDialogButtonBox>
#include <QTabWidget>
#include <QVBoxLayout>
#include "DolphinQt/Achievements/AchievementSettingsWidget.h"
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
AchievementsWindow::AchievementsWindow(QWidget* parent) : QDialog(parent)
{
setWindowTitle(tr("Achievements"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
CreateMainLayout();
ConnectWidgets();
}
void AchievementsWindow::showEvent(QShowEvent* event)
{
QDialog::showEvent(event);
update();
}
void AchievementsWindow::CreateMainLayout()
{
auto* layout = new QVBoxLayout();
m_tab_widget = new QTabWidget();
m_tab_widget->addTab(
GetWrappedWidget(new AchievementSettingsWidget(m_tab_widget, this), this, 125, 100),
tr("Settings"));
m_button_box = new QDialogButtonBox(QDialogButtonBox::Close);
layout->addWidget(m_tab_widget);
layout->addWidget(m_button_box);
WrapInScrollArea(this, layout);
}
void AchievementsWindow::ConnectWidgets()
{
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
void AchievementsWindow::UpdateData()
{
update();
}
#endif // USE_RETRO_ACHIEVEMENTS

View file

@ -0,0 +1,28 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#ifdef USE_RETRO_ACHIEVEMENTS
#include <QDialog>
class QTabWidget;
class QDialogButtonBox;
class AchievementsWindow : public QDialog
{
Q_OBJECT
public:
explicit AchievementsWindow(QWidget* parent);
void UpdateData();
private:
void CreateMainLayout();
void showEvent(QShowEvent* event);
void ConnectWidgets();
QTabWidget* m_tab_widget;
QDialogButtonBox* m_button_box;
};
#endif // USE_RETRO_ACHIEVEMENTS

View file

@ -5,15 +5,15 @@ endif()
if (MSVC)
if(_M_ARM_64)
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/Externals/Qt/Qt6.3.0/ARM64")
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/Externals/Qt/Qt6.5.1/ARM64")
else()
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/Externals/Qt/Qt6.3.0/x64")
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/Externals/Qt/Qt6.5.1/x64")
endif()
endif()
set(CMAKE_AUTOMOC ON)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Svg)
message(STATUS "Found Qt version ${Qt6_VERSION}")
set_property(TARGET Qt6::Core PROPERTY INTERFACE_COMPILE_FEATURES "")
@ -27,6 +27,10 @@ add_executable(dolphin-mpn
CheatSearchWidget.h
CheatsManager.cpp
CheatsManager.h
Achievements/AchievementSettingsWidget.cpp
Achievements/AchievementSettingsWidget.h
Achievements/AchievementsWindow.cpp
Achievements/AchievementsWindow.h
Config/ARCodeWidget.cpp
Config/ARCodeWidget.h
Config/CheatCodeEditor.cpp
@ -43,6 +47,8 @@ add_executable(dolphin-mpn
Config/ConfigControls/ConfigInteger.h
Config/ConfigControls/ConfigRadio.cpp
Config/ConfigControls/ConfigRadio.h
Config/ConfigControls/ConfigFloatSlider.cpp
Config/ConfigControls/ConfigFloatSlider.h
Config/ConfigControls/ConfigSlider.cpp
Config/ConfigControls/ConfigSlider.h
Config/ControllerInterface/ControllerInterfaceWindow.cpp
@ -81,6 +87,8 @@ add_executable(dolphin-mpn
Config/Graphics/GraphicsWindow.h
Config/Graphics/HacksWidget.cpp
Config/Graphics/HacksWidget.h
Config/Graphics/ColorCorrectionConfigWindow.cpp
Config/Graphics/ColorCorrectionConfigWindow.h
Config/Graphics/PostProcessingConfigWindow.cpp
Config/Graphics/PostProcessingConfigWindow.h
Config/GraphicsModListWidget.cpp
@ -125,6 +133,8 @@ add_executable(dolphin-mpn
Config/Mapping/HotkeyStatesOther.h
Config/Mapping/HotkeyTAS.cpp
Config/Mapping/HotkeyTAS.h
Config/Mapping/HotkeyUSBEmu.cpp
Config/Mapping/HotkeyUSBEmu.h
Config/Mapping/HotkeyWii.cpp
Config/Mapping/HotkeyWii.h
Config/Mapping/IOWindow.cpp

View file

@ -0,0 +1,48 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "DolphinQt/Config/ConfigControls/ConfigFloatSlider.h"
#include <QSignalBlocker>
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigFloatSlider::ConfigFloatSlider(float minimum, float maximum,
const Config::Info<float>& setting, float step)
: ToolTipSlider(Qt::Horizontal), m_minimum(minimum), m_setting(setting), m_step(step)
{
const float range = maximum - minimum;
const int steps = std::round(range / step);
const int interval = std::round(range / steps);
const int current_value = std::round((Config::Get(m_setting) - minimum) / step);
setMinimum(0);
setMaximum(steps);
setTickInterval(interval);
setValue(current_value);
connect(this, &ConfigFloatSlider::valueChanged, this, &ConfigFloatSlider::Update);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
const int current_value = std::round((Config::Get(m_setting) - m_minimum) / m_step);
setValue(current_value);
});
}
void ConfigFloatSlider::Update(int value)
{
const float current_value = (m_step * value) + m_minimum;
Config::SetBaseOrCurrent(m_setting, current_value);
}
float ConfigFloatSlider::GetValue() const
{
return (m_step * value()) + m_minimum;
}

View file

@ -0,0 +1,30 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "DolphinQt/Config/ToolTipControls/ToolTipSlider.h"
namespace Config
{
template <typename T>
class Info;
}
// Automatically converts an int slider into a float one.
// Do not read the int values or ranges directly from it.
class ConfigFloatSlider : public ToolTipSlider
{
Q_OBJECT
public:
ConfigFloatSlider(float minimum, float maximum, const Config::Info<float>& setting, float step);
void Update(int value);
// Returns the adjusted float value
float GetValue() const;
private:
float m_minimum;
float m_step;
const Config::Info<float>& m_setting;
};

View file

@ -0,0 +1,181 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h"
#include <QCheckBox>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include "Core/Config/GraphicsSettings.h"
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include "DolphinQt/Config/ConfigControls/ConfigChoice.h"
#include "DolphinQt/Config/ConfigControls/ConfigFloatSlider.h"
#include "VideoCommon/VideoConfig.h"
ColorCorrectionConfigWindow::ColorCorrectionConfigWindow(QWidget* parent) : QDialog(parent)
{
setWindowTitle(tr("Color Correction Configuration"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
Create();
ConnectWidgets();
}
void ColorCorrectionConfigWindow::Create()
{
static const char TR_COLOR_SPACE_CORRECTION_DESCRIPTION[] = QT_TR_NOOP(
"Converts the colors to the color spaces that GC/Wii were meant to work with to sRGB/Rec.709."
"<br><br>There's no way of knowing what exact color space games were meant for,"
"<br>given there were multiple standards and most games didn't acknowledge them,"
"<br>so it's not correct to assume a format from the game disc region."
"<br>Just pick the one that looks more natural to you,"
" or match it with the region the game was developed in."
"<br><br>HDR output is required to show all the colors from the PAL and NTSC-J color spaces."
"<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>");
static const char TR_GAME_GAMMA_DESCRIPTION[] =
QT_TR_NOOP("NTSC-M and NTSC-J target gamma ~2.2. PAL targets gamma ~2.8."
"<br>None of the two were necessarily followed by games or TVs. 2.35 is a good "
"generic value for all regions."
"<br>If a game allows you to chose a gamma value, match it here.");
static const char TR_GAMMA_CORRECTION_DESCRIPTION[] = QT_TR_NOOP(
"Converts the gamma from what the game targeted to what your current SDR display targets."
"<br>Monitors often target sRGB. TVs often target 2.2."
"<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>");
// Color Space:
auto* const color_space_box = new QGroupBox(tr("Color Space"));
auto* const color_space_layout = new QGridLayout();
color_space_layout->setVerticalSpacing(7);
color_space_layout->setColumnStretch(1, 1);
color_space_box->setLayout(color_space_layout);
m_correct_color_space =
new ConfigBool(tr("Correct Color Space"), Config::GFX_CC_CORRECT_COLOR_SPACE);
color_space_layout->addWidget(m_correct_color_space, 0, 0);
m_correct_color_space->SetDescription(tr(TR_COLOR_SPACE_CORRECTION_DESCRIPTION));
// "ColorCorrectionRegion"
const QStringList game_color_space_enum{tr("NTSC-M (SMPTE 170M)"), tr("NTSC-J (ARIB TR-B9)"),
tr("PAL (EBU)")};
m_game_color_space = new ConfigChoice(game_color_space_enum, Config::GFX_CC_GAME_COLOR_SPACE);
color_space_layout->addWidget(new QLabel(tr("Game Color Space")), 1, 0);
color_space_layout->addWidget(m_game_color_space, 1, 1);
m_game_color_space->setEnabled(m_correct_color_space->isChecked());
// Gamma:
auto* const gamma_box = new QGroupBox(tr("Gamma"));
auto* const gamma_layout = new QGridLayout();
gamma_layout->setVerticalSpacing(7);
gamma_layout->setColumnStretch(1, 1);
gamma_box->setLayout(gamma_layout);
m_game_gamma = new ConfigFloatSlider(Config::GFX_CC_GAME_GAMMA_MIN, Config::GFX_CC_GAME_GAMMA_MAX,
Config::GFX_CC_GAME_GAMMA, 0.01f);
gamma_layout->addWidget(new QLabel(tr("Game Gamma")), 0, 0);
gamma_layout->addWidget(m_game_gamma, 0, 1);
m_game_gamma->SetDescription(tr(TR_GAME_GAMMA_DESCRIPTION));
m_game_gamma_value = new QLabel(tr(""));
gamma_layout->addWidget(m_game_gamma_value, 0, 2);
m_correct_gamma = new ConfigBool(tr("Correct SDR Gamma"), Config::GFX_CC_CORRECT_GAMMA);
gamma_layout->addWidget(m_correct_gamma, 1, 0);
m_correct_gamma->SetDescription(tr(TR_GAMMA_CORRECTION_DESCRIPTION));
m_sdr_display_gamma_srgb =
new ConfigBool(tr("SDR Display Gamma sRGB"), Config::GFX_CC_SDR_DISPLAY_GAMMA_SRGB);
gamma_layout->addWidget(m_sdr_display_gamma_srgb, 2, 0);
m_sdr_display_custom_gamma =
new ConfigFloatSlider(Config::GFX_CC_DISPLAY_GAMMA_MIN, Config::GFX_CC_DISPLAY_GAMMA_MAX,
Config::GFX_CC_SDR_DISPLAY_CUSTOM_GAMMA, 0.01f);
gamma_layout->addWidget(new QLabel(tr("SDR Display Custom Gamma")), 3, 0);
gamma_layout->addWidget(m_sdr_display_custom_gamma, 3, 1);
m_sdr_display_custom_gamma_value = new QLabel(tr(""));
gamma_layout->addWidget(m_sdr_display_custom_gamma_value, 3, 2);
m_sdr_display_gamma_srgb->setEnabled(m_correct_gamma->isChecked());
m_sdr_display_custom_gamma->setEnabled(m_correct_gamma->isChecked() &&
!m_sdr_display_gamma_srgb->isChecked());
m_game_gamma_value->setText(QString::asprintf("%f", m_game_gamma->GetValue()));
m_sdr_display_custom_gamma_value->setText(
QString::asprintf("%f", m_sdr_display_custom_gamma->GetValue()));
// HDR:
auto* const hdr_box = new QGroupBox(tr("HDR"));
auto* const hdr_layout = new QGridLayout();
hdr_layout->setVerticalSpacing(7);
hdr_layout->setColumnStretch(1, 1);
hdr_box->setLayout(hdr_layout);
m_hdr_paper_white_nits = new ConfigFloatSlider(Config::GFX_CC_HDR_PAPER_WHITE_NITS_MIN,
Config::GFX_CC_HDR_PAPER_WHITE_NITS_MAX,
Config::GFX_CC_HDR_PAPER_WHITE_NITS, 1.f);
hdr_layout->addWidget(new QLabel(tr("HDR Paper White Nits")), 0, 0);
hdr_layout->addWidget(m_hdr_paper_white_nits, 0, 1);
m_hdr_paper_white_nits_value = new QLabel(tr(""));
hdr_layout->addWidget(m_hdr_paper_white_nits_value, 0, 2);
m_hdr_paper_white_nits_value->setText(
QString::asprintf("%f", m_hdr_paper_white_nits->GetValue()));
// Other:
m_button_box = new QDialogButtonBox(QDialogButtonBox::Close);
auto* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setAlignment(Qt::AlignTop);
layout->addWidget(color_space_box);
layout->addWidget(gamma_box);
layout->addWidget(hdr_box);
layout->addWidget(m_button_box);
setLayout(layout);
}
void ColorCorrectionConfigWindow::ConnectWidgets()
{
connect(m_correct_color_space, &QCheckBox::toggled, this,
[this] { m_game_color_space->setEnabled(m_correct_color_space->isChecked()); });
connect(m_game_gamma, &ConfigFloatSlider::valueChanged, this, [this] {
m_game_gamma_value->setText(QString::asprintf("%f", m_game_gamma->GetValue()));
});
connect(m_correct_gamma, &QCheckBox::toggled, this, [this] {
// The "m_game_gamma" shouldn't be grayed out as it can still affect the color space correction
// For the moment we leave this enabled even when we are outputting in HDR
// (which means they'd have no influence on the final image),
// mostly because we don't have a simple way to determine if HDR is engaged from here
m_sdr_display_gamma_srgb->setEnabled(m_correct_gamma->isChecked());
m_sdr_display_custom_gamma->setEnabled(m_correct_gamma->isChecked() &&
!m_sdr_display_gamma_srgb->isChecked());
});
connect(m_sdr_display_gamma_srgb, &QCheckBox::toggled, this, [this] {
m_sdr_display_custom_gamma->setEnabled(m_correct_gamma->isChecked() &&
!m_sdr_display_gamma_srgb->isChecked());
});
connect(m_sdr_display_custom_gamma, &ConfigFloatSlider::valueChanged, this, [this] {
m_sdr_display_custom_gamma_value->setText(
QString::asprintf("%f", m_sdr_display_custom_gamma->GetValue()));
});
connect(m_hdr_paper_white_nits, &ConfigFloatSlider::valueChanged, this, [this] {
m_hdr_paper_white_nits_value->setText(
QString::asprintf("%f", m_hdr_paper_white_nits->GetValue()));
});
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
}

View file

@ -0,0 +1,36 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QDialog>
class QWidget;
class QLabel;
class ConfigBool;
class ConfigChoice;
class ConfigFloatSlider;
class QDialogButtonBox;
class ColorCorrectionConfigWindow final : public QDialog
{
Q_OBJECT
public:
explicit ColorCorrectionConfigWindow(QWidget* parent);
private:
void Create();
void ConnectWidgets();
ConfigBool* m_correct_color_space;
ConfigChoice* m_game_color_space;
ConfigFloatSlider* m_game_gamma;
QLabel* m_game_gamma_value;
ConfigBool* m_correct_gamma;
ConfigBool* m_sdr_display_gamma_srgb;
ConfigFloatSlider* m_sdr_display_custom_gamma;
QLabel* m_sdr_display_custom_gamma_value;
ConfigFloatSlider* m_hdr_paper_white_nits;
QLabel* m_hdr_paper_white_nits_value;
QDialogButtonBox* m_button_box;
};

View file

@ -18,13 +18,12 @@
#include "DolphinQt/Config/ConfigControls/ConfigChoice.h"
#include "DolphinQt/Config/ConfigControls/ConfigRadio.h"
#include "DolphinQt/Config/ConfigControls/ConfigSlider.h"
#include "DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h"
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/Settings.h"
#include "UICommon/VideoUtils.h"
#include "VideoCommon/PostProcessing.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
@ -104,6 +103,8 @@ void EnhancementsWidget::CreateWidgets()
m_texture_filtering_combo->addItem(tr("Force Linear and 16x Anisotropic"),
TEXTURE_FILTERING_FORCE_LINEAR_ANISO_16X);
m_configure_color_correction = new NonDefaultQPushButton(tr("Configure"));
m_pp_effect = new ToolTipComboBox();
m_configure_pp_effect = new NonDefaultQPushButton(tr("Configure"));
m_scaled_efb_copy = new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED);
@ -118,6 +119,7 @@ void EnhancementsWidget::CreateWidgets()
new ConfigBool(tr("Disable Copy Filter"), Config::GFX_ENHANCE_DISABLE_COPY_FILTER);
m_arbitrary_mipmap_detection = new ConfigBool(tr("Arbitrary Mipmap Detection"),
Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION);
m_hdr = new ConfigBool(tr("HDR Post-Processing"), Config::GFX_ENHANCE_HDR_OUTPUT);
int row = 0;
enhancements_layout->addWidget(new QLabel(tr("Internal Resolution:")), row, 0);
@ -132,6 +134,10 @@ void EnhancementsWidget::CreateWidgets()
enhancements_layout->addWidget(m_texture_filtering_combo, row, 1, 1, -1);
++row;
enhancements_layout->addWidget(new QLabel(tr("Color Correction:")), row, 0);
enhancements_layout->addWidget(m_configure_color_correction, row, 1, 1, -1);
++row;
enhancements_layout->addWidget(new QLabel(tr("Post-Processing Effect:")), row, 0);
enhancements_layout->addWidget(m_pp_effect, row, 1);
enhancements_layout->addWidget(m_configure_pp_effect, row, 2);
@ -150,6 +156,7 @@ void EnhancementsWidget::CreateWidgets()
++row;
enhancements_layout->addWidget(m_disable_copy_filter, row, 0);
enhancements_layout->addWidget(m_hdr, row, 1, 1, -1);
++row;
// Stereoscopy
@ -190,11 +197,14 @@ void EnhancementsWidget::ConnectWidgets()
[this](int) { SaveSettings(); });
connect(m_3d_mode, qOverload<int>(&QComboBox::currentIndexChanged), [this] {
m_block_save = true;
m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing);
LoadPPShaders();
m_block_save = false;
SaveSettings();
});
connect(m_configure_color_correction, &QPushButton::clicked, this,
&EnhancementsWidget::ConfigureColorCorrection);
connect(m_configure_pp_effect, &QPushButton::clicked, this,
&EnhancementsWidget::ConfigurePostProcessingShader);
}
@ -260,18 +270,38 @@ void EnhancementsWidget::LoadSettings()
m_block_save = true;
// Anti-Aliasing
const int aa_selection = Config::Get(Config::GFX_MSAA);
const u32 aa_selection = Config::Get(Config::GFX_MSAA);
const bool ssaa = Config::Get(Config::GFX_SSAA);
const int aniso = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
const TextureFilteringMode tex_filter_mode =
Config::Get(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING);
m_aa_combo->clear();
for (const auto& option : VideoUtils::GetAvailableAntialiasingModes(m_msaa_modes))
m_aa_combo->addItem(option == "None" ? tr("None") : QString::fromStdString(option));
m_aa_combo->setCurrentText(
QString::fromStdString(std::to_string(aa_selection) + "x " + (ssaa ? "SSAA" : "MSAA")));
for (const u32 aa_mode : g_Config.backend_info.AAModes)
{
if (aa_mode == 1)
m_aa_combo->addItem(tr("None"), 1);
else
m_aa_combo->addItem(tr("%1x MSAA").arg(aa_mode), static_cast<int>(aa_mode));
if (aa_mode == aa_selection && !ssaa)
m_aa_combo->setCurrentIndex(m_aa_combo->count() - 1);
}
if (g_Config.backend_info.bSupportsSSAA)
{
for (const u32 aa_mode : g_Config.backend_info.AAModes)
{
if (aa_mode != 1) // don't show "None" twice
{
// Mark SSAA using negative values in the variant
m_aa_combo->addItem(tr("%1x SSAA").arg(aa_mode), -static_cast<int>(aa_mode));
if (aa_mode == aa_selection && ssaa)
m_aa_combo->setCurrentIndex(m_aa_combo->count() - 1);
}
}
}
m_aa_combo->setEnabled(m_aa_combo->count() > 1);
switch (tex_filter_mode)
@ -293,6 +323,8 @@ void EnhancementsWidget::LoadSettings()
break;
}
m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing);
// Post Processing Shader
LoadPPShaders();
@ -302,6 +334,9 @@ void EnhancementsWidget::LoadSettings()
m_3d_convergence->setEnabled(supports_stereoscopy);
m_3d_depth->setEnabled(supports_stereoscopy);
m_3d_swap_eyes->setEnabled(supports_stereoscopy);
m_hdr->setEnabled(g_Config.backend_info.bSupportsHDROutput);
m_block_save = false;
}
@ -310,22 +345,10 @@ void EnhancementsWidget::SaveSettings()
if (m_block_save)
return;
bool is_ssaa = m_aa_combo->currentText().endsWith(QStringLiteral("SSAA"));
int aa_value = m_aa_combo->currentIndex();
if (aa_value == 0)
{
aa_value = 1;
}
else
{
if (aa_value > m_msaa_modes)
aa_value -= m_msaa_modes;
aa_value = std::pow(2, aa_value);
}
Config::SetBaseOrCurrent(Config::GFX_MSAA, static_cast<unsigned int>(aa_value));
const u32 aa_value = static_cast<u32>(std::abs(m_aa_combo->currentData().toInt()));
const bool is_ssaa = m_aa_combo->currentData().toInt() < 0;
Config::SetBaseOrCurrent(Config::GFX_MSAA, aa_value);
Config::SetBaseOrCurrent(Config::GFX_SSAA, is_ssaa);
const int texture_filtering_selection = m_texture_filtering_combo->currentData().toInt();
@ -430,6 +453,9 @@ void EnhancementsWidget::AddDescriptions()
"scaling filter selected by the game.<br><br>Any option except 'Default' will alter the look "
"of the game's textures and might cause issues in a small number of "
"games.<br><br><dolphin_emphasis>If unsure, select 'Default'.</dolphin_emphasis>");
static const char TR_COLOR_CORRECTION_DESCRIPTION[] =
QT_TR_NOOP("A group of features to make the colors more accurate,"
" matching the color space Wii and GC games were meant for.");
static const char TR_POSTPROCESSING_DESCRIPTION[] =
QT_TR_NOOP("Applies a post-processing effect after rendering a frame.<br><br "
"/><dolphin_emphasis>If unsure, select (off).</dolphin_emphasis>");
@ -492,6 +518,13 @@ void EnhancementsWidget::AddDescriptions()
"reduce stutter in games that frequently load new textures. This feature is not compatible "
"with GPU Texture Decoding.<br><br><dolphin_emphasis>If unsure, leave this "
"checked.</dolphin_emphasis>");
static const char TR_HDR_DESCRIPTION[] = QT_TR_NOOP(
"Enables scRGB HDR output (if supported by your graphics backend and monitor)."
" Fullscreen might be required."
"<br><br>This gives post process shaders more room for accuracy, allows \"AutoHDR\" "
"post-process shaders to work, and allows to fully display the PAL and NTSC-J color spaces."
"<br><br>Note that games still render in SDR internally."
"<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>");
m_ir_combo->SetTitle(tr("Internal Resolution"));
m_ir_combo->SetDescription(tr(TR_INTERNAL_RESOLUTION_DESCRIPTION));
@ -502,6 +535,8 @@ void EnhancementsWidget::AddDescriptions()
m_texture_filtering_combo->SetTitle(tr("Texture Filtering"));
m_texture_filtering_combo->SetDescription(tr(TR_FORCE_TEXTURE_FILTERING_DESCRIPTION));
m_configure_color_correction->setToolTip(tr(TR_COLOR_CORRECTION_DESCRIPTION));
m_pp_effect->SetTitle(tr("Post-Processing Effect"));
m_pp_effect->SetDescription(tr(TR_POSTPROCESSING_DESCRIPTION));
@ -519,6 +554,8 @@ void EnhancementsWidget::AddDescriptions()
m_arbitrary_mipmap_detection->SetDescription(tr(TR_ARBITRARY_MIPMAP_DETECTION_DESCRIPTION));
m_hdr->SetDescription(tr(TR_HDR_DESCRIPTION));
m_3d_mode->SetTitle(tr("Stereoscopic 3D Mode"));
m_3d_mode->SetDescription(tr(TR_3D_MODE_DESCRIPTION));
@ -531,6 +568,11 @@ void EnhancementsWidget::AddDescriptions()
m_3d_swap_eyes->SetDescription(tr(TR_3D_SWAP_EYES_DESCRIPTION));
}
void EnhancementsWidget::ConfigureColorCorrection()
{
ColorCorrectionConfigWindow(this).exec();
}
void EnhancementsWidget::ConfigurePostProcessingShader()
{
const std::string shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);

View file

@ -30,6 +30,7 @@ private:
void CreateWidgets();
void ConnectWidgets();
void AddDescriptions();
void ConfigureColorCorrection();
void ConfigurePostProcessingShader();
void LoadPPShaders();
@ -38,6 +39,7 @@ private:
ToolTipComboBox* m_aa_combo;
ToolTipComboBox* m_texture_filtering_combo;
ToolTipComboBox* m_pp_effect;
QPushButton* m_configure_color_correction;
QPushButton* m_configure_pp_effect;
ConfigBool* m_scaled_efb_copy;
ConfigBool* m_per_pixel_lighting;
@ -46,6 +48,7 @@ private:
ConfigBool* m_force_24bit_color;
ConfigBool* m_disable_copy_filter;
ConfigBool* m_arbitrary_mipmap_detection;
ConfigBool* m_hdr;
// Stereoscopy
ConfigChoice* m_3d_mode;

View file

@ -24,7 +24,7 @@
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
GraphicsWindow::GraphicsWindow(MainWindow* parent) : QDialog(parent)
GraphicsWindow::GraphicsWindow(MainWindow* parent) : QDialog(parent), m_main_window(parent)
{
CreateMainLayout();
@ -68,7 +68,7 @@ void GraphicsWindow::CreateMainLayout()
void GraphicsWindow::OnBackendChanged(const QString& backend_name)
{
Config::SetBase(Config::MAIN_GFX_BACKEND, backend_name.toStdString());
VideoBackendBase::PopulateBackendInfoFromUI();
VideoBackendBase::PopulateBackendInfoFromUI(m_main_window->GetWindowSystemInfo());
setWindowTitle(
tr("%1 Graphics Configuration").arg(tr(g_video_backend->GetDisplayName().c_str())));

View file

@ -28,4 +28,6 @@ signals:
private:
void CreateMainLayout();
void OnBackendChanged(const QString& backend);
MainWindow* const m_main_window;
};

View file

@ -269,7 +269,6 @@ u32 PostProcessingConfigWindow::ConfigGroup::AddInteger(PostProcessingConfigWind
for (size_t i = 0; i < vector_size; ++i)
{
const int current_value = m_config_option->m_integer_values[i];
const double range =
m_config_option->m_integer_max_values[i] - m_config_option->m_integer_min_values[i];
// "How many steps we have is the range divided by the step interval configured.
@ -278,6 +277,9 @@ u32 PostProcessingConfigWindow::ConfigGroup::AddInteger(PostProcessingConfigWind
// Round up so if it is outside our range, then set it to the minimum or maximum"
const int steps =
std::ceil(range / static_cast<double>(m_config_option->m_integer_step_values[i]));
const int current_value = std::round(
(m_config_option->m_integer_values[i] - m_config_option->m_integer_min_values[i]) /
static_cast<double>(m_config_option->m_integer_max_values[i]));
auto* const slider = new QSlider(Qt::Orientation::Horizontal);
slider->setMinimum(0);

View file

@ -0,0 +1,39 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "DolphinQt/Config/Mapping/HotkeyUSBEmu.h"
#include <QGroupBox>
#include <QHBoxLayout>
#include "Core/HotkeyManager.h"
HotkeyUSBEmu::HotkeyUSBEmu(MappingWindow* window) : MappingWidget(window)
{
CreateMainLayout();
}
void HotkeyUSBEmu::CreateMainLayout()
{
m_main_layout = new QHBoxLayout();
m_main_layout->addWidget(
CreateGroupBox(tr("USB Device Emulation"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_USB_EMU)));
setLayout(m_main_layout);
}
InputConfig* HotkeyUSBEmu::GetConfig()
{
return HotkeyManagerEmu::GetConfig();
}
void HotkeyUSBEmu::LoadSettings()
{
HotkeyManagerEmu::LoadConfig();
}
void HotkeyUSBEmu::SaveSettings()
{
HotkeyManagerEmu::GetConfig()->SaveConfig();
}

View file

@ -0,0 +1,26 @@
#pragma once
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "DolphinQt/Config/Mapping/MappingWidget.h"
class QHBoxLayout;
class HotkeyUSBEmu final : public MappingWidget
{
Q_OBJECT
public:
explicit HotkeyUSBEmu(MappingWindow* window);
InputConfig* GetConfig() override;
private:
void LoadSettings() override;
void SaveSettings() override;
void CreateMainLayout();
// Main
QHBoxLayout* m_main_layout;
};

View file

@ -281,7 +281,7 @@ void MappingWidget::CreateControl(const ControllerEmu::Control* control, QFormLa
button->setMinimumWidth(100);
button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
const bool translate = control->translate == ControllerEmu::Translate;
const bool translate = control->translate == ControllerEmu::Translatability::Translate;
const QString translated_name =
translate ? tr(control->ui_name.c_str()) : QString::fromStdString(control->ui_name);
layout->addRow(translated_name, button);

View file

@ -39,6 +39,7 @@
#include "DolphinQt/Config/Mapping/HotkeyStates.h"
#include "DolphinQt/Config/Mapping/HotkeyStatesOther.h"
#include "DolphinQt/Config/Mapping/HotkeyTAS.h"
#include "DolphinQt/Config/Mapping/HotkeyUSBEmu.h"
#include "DolphinQt/Config/Mapping/HotkeyWii.h"
#include "DolphinQt/Config/Mapping/WiimoteEmuExtension.h"
#include "DolphinQt/Config/Mapping/WiimoteEmuExtensionMotionInput.h"
@ -450,6 +451,7 @@ void MappingWindow::SetMappingType(MappingWindow::Type type)
AddWidget(tr("Wii and Wii Remote"), new HotkeyWii(this));
AddWidget(tr("Controller Profile"), new HotkeyControllerProfile(this));
AddWidget(tr("Graphics"), new HotkeyGraphics(this));
AddWidget(tr("USB Emulation"), new HotkeyUSBEmu(this));
// i18n: Stereoscopic 3D
AddWidget(tr("3D"), new Hotkey3D(this));
AddWidget(tr("Save and Load State"), new HotkeyStates(this));

View file

@ -251,7 +251,7 @@ void BreakpointDialog::OnAddressTypeChanged()
void BreakpointDialog::accept()
{
auto invalid_input = [this](QString field) {
auto invalid_input = [this](const QString& field) {
ModalMessageBox::critical(this, tr("Error"),
tr("Invalid input for the field \"%1\"").arg(field));
};
@ -323,7 +323,7 @@ void BreakpointDialog::accept()
void BreakpointDialog::ShowConditionHelp()
{
const auto message = QStringLiteral(
const auto message = tr(
"Conditions:\n"
"Sets an expression that is evaluated when a breakpoint is hit. If the expression is false "
"or 0, the breakpoint is ignored until hit again. Statements should be separated by a comma. "

View file

@ -168,7 +168,7 @@ void BreakpointWidget::Update()
int i = 0;
m_table->setRowCount(i);
const auto create_item = [](const QString string = {}) {
const auto create_item = [](const QString& string = {}) {
QTableWidgetItem* item = new QTableWidgetItem(string);
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
return item;

View file

@ -279,7 +279,7 @@ void CodeDiffDialog::OnExclude()
}
}
std::vector<Diff> CodeDiffDialog::CalculateSymbolsFromProfile()
std::vector<Diff> CodeDiffDialog::CalculateSymbolsFromProfile() const
{
Profiler::ProfileStats prof_stats;
auto& blockstats = prof_stats.block_stats;
@ -288,23 +288,23 @@ std::vector<Diff> CodeDiffDialog::CalculateSymbolsFromProfile()
current.reserve(20000);
// Convert blockstats to smaller struct Diff. Exclude repeat functions via symbols.
for (auto& iter : blockstats)
for (const auto& iter : blockstats)
{
Diff tmp_diff;
std::string symbol = g_symbolDB.GetDescription(iter.addr);
if (!std::any_of(current.begin(), current.end(),
[&symbol](Diff& v) { return v.symbol == symbol; }))
[&symbol](const Diff& v) { return v.symbol == symbol; }))
{
tmp_diff.symbol = symbol;
tmp_diff.addr = iter.addr;
tmp_diff.hits = iter.run_count;
tmp_diff.total_hits = iter.run_count;
current.push_back(tmp_diff);
current.push_back(Diff{
.addr = iter.addr,
.symbol = std::move(symbol),
.hits = static_cast<u32>(iter.run_count),
.total_hits = static_cast<u32>(iter.run_count),
});
}
}
sort(current.begin(), current.end(),
[](const Diff& v1, const Diff& v2) { return (v1.symbol < v2.symbol); });
std::sort(current.begin(), current.end(),
[](const Diff& v1, const Diff& v2) { return (v1.symbol < v2.symbol); });
return current;
}
@ -361,7 +361,7 @@ void CodeDiffDialog::Update(bool include)
OnExclude();
}
const auto create_item = [](const QString string = {}, const u32 address = 0x00000000) {
const auto create_item = [](const QString& string = {}, const u32 address = 0x00000000) {
QTableWidgetItem* item = new QTableWidgetItem(string);
item->setData(Qt::UserRole, address);
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);

View file

@ -38,7 +38,7 @@ private:
void ClearBlockCache();
void OnClickItem();
void OnRecord(bool enabled);
std::vector<Diff> CalculateSymbolsFromProfile();
std::vector<Diff> CalculateSymbolsFromProfile() const;
void OnInclude();
void OnExclude();
void RemoveMissingSymbolsFromIncludes(const std::vector<Diff>& symbol_diff);

View file

@ -609,7 +609,7 @@ AddressSpace::Type MemoryViewWidget::GetAddressSpace() const
return m_address_space;
}
std::vector<u8> MemoryViewWidget::ConvertTextToBytes(Type type, QString input_text)
std::vector<u8> MemoryViewWidget::ConvertTextToBytes(Type type, QStringView input_text) const
{
if (type == Type::Null)
return {};

View file

@ -60,7 +60,7 @@ public:
void UpdateFont();
void ToggleBreakpoint(u32 addr, bool row);
std::vector<u8> ConvertTextToBytes(Type type, QString input_text);
std::vector<u8> ConvertTextToBytes(Type type, QStringView input_text) const;
void SetAddressSpace(AddressSpace::Type address_space);
AddressSpace::Type GetAddressSpace() const;
void SetDisplay(Type type, int bytes_per_row, int alignment, bool dual_view);

View file

@ -261,7 +261,7 @@ void NetworkWidget::Update()
return;
m_socket_table->setRowCount(0);
for (u32 wii_fd = 0; wii_fd < IOS::HLE::WII_SOCKET_FD_MAX; wii_fd++)
for (s32 wii_fd = 0; wii_fd < IOS::HLE::WII_SOCKET_FD_MAX; wii_fd++)
{
m_socket_table->insertRow(wii_fd);
const s32 host_fd = socket_manager->GetHostSocket(wii_fd);
@ -275,7 +275,7 @@ void NetworkWidget::Update()
m_socket_table->resizeColumnsToContents();
m_ssl_table->setRowCount(0);
for (u32 ssl_id = 0; ssl_id < IOS::HLE::NET_SSL_MAXINSTANCES; ssl_id++)
for (s32 ssl_id = 0; ssl_id < IOS::HLE::NET_SSL_MAXINSTANCES; ssl_id++)
{
m_ssl_table->insertRow(ssl_id);
s32 host_fd = -1;
@ -328,7 +328,7 @@ QGroupBox* NetworkWidget::CreateSocketTableGroup()
m_socket_table = new QTableWidget();
// i18n: FD stands for file descriptor (and in this case refers to sockets, not regular files)
QStringList header{tr("FD"), tr("Domain"), tr("Type"), tr("State"), tr("Blocking"), tr("Name")};
m_socket_table->setColumnCount(header.size());
m_socket_table->setColumnCount(static_cast<int>(header.size()));
m_socket_table->setHorizontalHeaderLabels(header);
m_socket_table->setTabKeyNavigation(false);
@ -350,7 +350,7 @@ QGroupBox* NetworkWidget::CreateSSLContextGroup()
m_ssl_table = new QTableWidget();
QStringList header{tr("ID"), tr("Domain"), tr("Type"), tr("State"), tr("Name"), tr("Hostname")};
m_ssl_table->setColumnCount(header.size());
m_ssl_table->setColumnCount(static_cast<int>(header.size()));
m_ssl_table->setHorizontalHeaderLabels(header);
m_ssl_table->setTabKeyNavigation(false);

View file

@ -55,6 +55,8 @@
<ClCompile Include="CheatSearchFactoryWidget.cpp" />
<ClCompile Include="CheatSearchWidget.cpp" />
<ClCompile Include="CheatsManager.cpp" />
<ClCompile Include="Achievements\AchievementSettingsWidget.cpp" />
<ClCompile Include="Achievements\AchievementsWindow.cpp" />
<ClCompile Include="Config\ARCodeWidget.cpp" />
<ClCompile Include="Config\CheatCodeEditor.cpp" />
<ClCompile Include="Config\CheatWarningWidget.cpp" />
@ -63,6 +65,7 @@
<ClCompile Include="Config\ConfigControls\ConfigChoice.cpp" />
<ClCompile Include="Config\ConfigControls\ConfigInteger.cpp" />
<ClCompile Include="Config\ConfigControls\ConfigRadio.cpp" />
<ClCompile Include="Config\ConfigControls\ConfigFloatSlider.cpp" />
<ClCompile Include="Config\ConfigControls\ConfigSlider.cpp" />
<ClCompile Include="Config\ControllerInterface\ControllerInterfaceWindow.cpp" />
<ClCompile Include="Config\ControllerInterface\DualShockUDPClientAddServerDialog.cpp" />
@ -82,6 +85,7 @@
<ClCompile Include="Config\Graphics\GeneralWidget.cpp" />
<ClCompile Include="Config\Graphics\GraphicsWindow.cpp" />
<ClCompile Include="Config\Graphics\HacksWidget.cpp" />
<ClCompile Include="Config\Graphics\ColorCorrectionConfigWindow.cpp" />
<ClCompile Include="Config\Graphics\PostProcessingConfigWindow.cpp" />
<ClCompile Include="Config\GraphicsModListWidget.cpp" />
<ClCompile Include="Config\GraphicsModWarningWidget.cpp" />
@ -104,6 +108,7 @@
<ClCompile Include="Config\Mapping\HotkeyStates.cpp" />
<ClCompile Include="Config\Mapping\HotkeyStatesOther.cpp" />
<ClCompile Include="Config\Mapping\HotkeyTAS.cpp" />
<ClCompile Include="Config\Mapping\HotkeyUSBEmu.cpp" />
<ClCompile Include="Config\Mapping\HotkeyWii.cpp" />
<ClCompile Include="Config\Mapping\IOWindow.cpp" />
<ClCompile Include="Config\Mapping\MappingButton.cpp" />
@ -256,6 +261,8 @@
<QtMoc Include="CheatSearchFactoryWidget.h" />
<QtMoc Include="CheatSearchWidget.h" />
<QtMoc Include="CheatsManager.h" />
<QtMoc Include="Achievements\AchievementSettingsWidget.h" />
<QtMoc Include="Achievements\AchievementsWindow.h" />
<QtMoc Include="Config\ARCodeWidget.h" />
<QtMoc Include="Config\CheatWarningWidget.h" />
<QtMoc Include="Config\CommonControllersWidget.h" />
@ -263,6 +270,7 @@
<QtMoc Include="Config\ConfigControls\ConfigChoice.h" />
<QtMoc Include="Config\ConfigControls\ConfigInteger.h" />
<QtMoc Include="Config\ConfigControls\ConfigRadio.h" />
<QtMoc Include="Config\ConfigControls\ConfigFloatSlider.h" />
<QtMoc Include="Config\ConfigControls\ConfigSlider.h" />
<QtMoc Include="Config\ControllerInterface\ControllerInterfaceWindow.h" />
<QtMoc Include="Config\ControllerInterface\DualShockUDPClientAddServerDialog.h" />
@ -281,6 +289,7 @@
<QtMoc Include="Config\Graphics\GeneralWidget.h" />
<QtMoc Include="Config\Graphics\GraphicsWindow.h" />
<QtMoc Include="Config\Graphics\HacksWidget.h" />
<QtMoc Include="Config\Graphics\ColorCorrectionConfigWindow.h" />
<QtMoc Include="Config\Graphics\PostProcessingConfigWindow.h" />
<QtMoc Include="Config\GraphicsModListWidget.h" />
<QtMoc Include="Config\GraphicsModWarningWidget.h" />
@ -303,6 +312,7 @@
<QtMoc Include="Config\Mapping\HotkeyStates.h" />
<QtMoc Include="Config\Mapping\HotkeyStatesOther.h" />
<QtMoc Include="Config\Mapping\HotkeyTAS.h" />
<QtMoc Include="Config\Mapping\HotkeyUSBEmu.h" />
<QtMoc Include="Config\Mapping\HotkeyWii.h" />
<QtMoc Include="Config\Mapping\IOWindow.h" />
<QtMoc Include="Config\Mapping\MappingButton.h" />

View file

@ -502,7 +502,7 @@ void GCMemcardManager::ExportFiles(Memcard::SavefileFormat format)
}
}
void GCMemcardManager::ImportFiles(Slot slot, const std::vector<Memcard::Savefile>& savefiles)
void GCMemcardManager::ImportFiles(Slot slot, std::span<const Memcard::Savefile> savefiles)
{
auto& card = m_slot_memcard[slot];
if (!card)

View file

@ -3,10 +3,9 @@
#pragma once
#include <array>
#include <map>
#include <memory>
#include <utility>
#include <span>
#include <vector>
#include <QDialog>
@ -62,7 +61,7 @@ private:
std::vector<u8> GetSelectedFileIndices();
void ImportFiles(ExpansionInterface::Slot slot, const std::vector<Memcard::Savefile>& savefiles);
void ImportFiles(ExpansionInterface::Slot slot, std::span<const Memcard::Savefile> savefiles);
void CopyFiles();
void ImportFile();
@ -89,16 +88,17 @@ private:
QPushButton* m_fix_checksums_button;
// Slots
Common::EnumMap<std::map<u8, IconAnimationData>, ExpansionInterface::MAX_MEMCARD_SLOT>
m_slot_active_icons;
Common::EnumMap<std::unique_ptr<Memcard::GCMemcard>, ExpansionInterface::MAX_MEMCARD_SLOT>
m_slot_memcard;
Common::EnumMap<QGroupBox*, ExpansionInterface::MAX_MEMCARD_SLOT> m_slot_group;
Common::EnumMap<QLineEdit*, ExpansionInterface::MAX_MEMCARD_SLOT> m_slot_file_edit;
Common::EnumMap<QPushButton*, ExpansionInterface::MAX_MEMCARD_SLOT> m_slot_open_button;
Common::EnumMap<QPushButton*, ExpansionInterface::MAX_MEMCARD_SLOT> m_slot_create_button;
Common::EnumMap<QTableWidget*, ExpansionInterface::MAX_MEMCARD_SLOT> m_slot_table;
Common::EnumMap<QLabel*, ExpansionInterface::MAX_MEMCARD_SLOT> m_slot_stat_label;
template <typename T>
using SlotEnumMap = Common::EnumMap<T, ExpansionInterface::MAX_MEMCARD_SLOT>;
SlotEnumMap<std::map<u8, IconAnimationData>> m_slot_active_icons;
SlotEnumMap<std::unique_ptr<Memcard::GCMemcard>> m_slot_memcard;
SlotEnumMap<QGroupBox*> m_slot_group;
SlotEnumMap<QLineEdit*> m_slot_file_edit;
SlotEnumMap<QPushButton*> m_slot_open_button;
SlotEnumMap<QPushButton*> m_slot_create_button;
SlotEnumMap<QTableWidget*> m_slot_table;
SlotEnumMap<QLabel*> m_slot_stat_label;
ExpansionInterface::Slot m_active_slot;
u64 m_current_frame = 0;

View file

@ -59,16 +59,6 @@ Host* Host::GetInstance()
return s_instance;
}
void Host::DeclareAsHostThread()
{
tls_is_host_thread = true;
}
bool Host::IsHostThread()
{
return tls_is_host_thread;
}
void Host::SetRenderHandle(void* handle)
{
m_render_to_main = Config::Get(Config::MAIN_RENDER_TO_MAIN);

View file

@ -483,6 +483,13 @@ void HotkeyScheduler::Run()
ShowEmulationSpeed();
}
// USB Device Emulation
if (IsHotkey(HK_SKYLANDERS_PORTAL))
emit SkylandersPortalHotkey();
if (IsHotkey(HK_INFINITY_BASE))
emit InfinityBaseHotkey();
// Slot Saving / Loading
if (IsHotkey(HK_SAVE_STATE_SLOT_SELECTED))
emit StateSaveSlotHotkey();

View file

@ -65,6 +65,9 @@ signals:
void ToggleBreakpoint();
void AddBreakpoint();
void SkylandersPortalHotkey();
void InfinityBaseHotkey();
private:
void Run();
void CheckDebuggingHotkeys();

View file

@ -3,6 +3,8 @@
#include "DolphinQt/InfinityBase/InfinityBaseWindow.h"
#include <string>
#include <QCheckBox>
#include <QComboBox>
#include <QCompleter>
@ -19,6 +21,8 @@
#include "Common/IOFile.h"
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
#include "Core/IOS/USB/Emulated/Infinity.h"
#include "Core/System.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
@ -55,7 +59,7 @@ void InfinityBaseWindow::CreateMainWindow()
checkbox_layout->setAlignment(Qt::AlignHCenter);
m_checkbox = new QCheckBox(tr("Emulate Infinity Base"), this);
m_checkbox->setChecked(Config::Get(Config::MAIN_EMULATE_INFINITY_BASE));
connect(m_checkbox, &QCheckBox::toggled, [=](bool checked) { EmulateBase(checked); });
connect(m_checkbox, &QCheckBox::toggled, this, &InfinityBaseWindow::EmulateBase);
checkbox_layout->addWidget(m_checkbox);
checkbox_group->setLayout(checkbox_layout);
main_layout->addWidget(checkbox_group);
@ -71,19 +75,19 @@ void InfinityBaseWindow::CreateMainWindow()
auto* vbox_group = new QVBoxLayout();
auto* scroll_area = new QScrollArea();
AddFigureSlot(vbox_group, QString(tr("Play Set/Power Disc")), 0);
AddFigureSlot(vbox_group, tr("Play Set/Power Disc"), 0);
add_line(vbox_group);
AddFigureSlot(vbox_group, QString(tr("Player One")), 1);
AddFigureSlot(vbox_group, tr("Player One"), 1);
add_line(vbox_group);
AddFigureSlot(vbox_group, QString(tr("Player One Ability One")), 3);
AddFigureSlot(vbox_group, tr("Player One Ability One"), 3);
add_line(vbox_group);
AddFigureSlot(vbox_group, QString(tr("Player One Ability Two")), 5);
AddFigureSlot(vbox_group, tr("Player One Ability Two"), 5);
add_line(vbox_group);
AddFigureSlot(vbox_group, QString(tr("Player Two")), 2);
AddFigureSlot(vbox_group, tr("Player Two"), 2);
add_line(vbox_group);
AddFigureSlot(vbox_group, QString(tr("Player Two Ability One")), 4);
AddFigureSlot(vbox_group, tr("Player Two Ability One"), 4);
add_line(vbox_group);
AddFigureSlot(vbox_group, QString(tr("Player Two Ability Two")), 6);
AddFigureSlot(vbox_group, tr("Player Two Ability Two"), 6);
m_group_figures->setLayout(vbox_group);
scroll_area->setWidget(m_group_figures);
@ -139,8 +143,6 @@ void InfinityBaseWindow::LoadFigure(u8 slot)
s_last_figure_path = QFileInfo(file_path).absolutePath() + QLatin1Char('/');
m_edit_figures[slot]->setText(QFileInfo(file_path).fileName());
LoadFigurePath(slot, file_path);
}
@ -191,7 +193,7 @@ CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(paren
auto* combo_figlist = new QComboBox();
QStringList filterlist;
u32 first_entry = 0;
for (const auto& entry : Core::System::GetInstance().GetInfinityBase().GetFigureList())
for (const auto& entry : IOS::HLE::USB::InfinityBase::GetFigureList())
{
const auto figure = entry.second;
// Only display entry if it is a piece appropriate for the slot
@ -201,8 +203,9 @@ CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(paren
((slot == 3 || slot == 4 || slot == 5 || slot == 6) &&
(figure > 0x2DC6C0 && figure < 0x3D08FF)))
{
combo_figlist->addItem(QString::fromStdString(entry.first), QVariant(figure));
filterlist << QString::fromStdString(entry.first);
const auto figure_name = QString::fromStdString(entry.first);
combo_figlist->addItem(figure_name, QVariant(figure));
filterlist << figure_name;
if (first_entry == 0)
{
first_entry = figure;
@ -228,7 +231,7 @@ CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(paren
auto* hbox_idvar = new QHBoxLayout();
auto* label_id = new QLabel(tr("Figure Number:"));
auto* edit_num = new QLineEdit(QString::fromStdString(std::to_string(first_entry)));
auto* edit_num = new QLineEdit(QString::number(first_entry));
auto* rxv = new QRegularExpressionValidator(QRegularExpression(QStringLiteral("\\d*")), this);
edit_num->setValidator(rxv);
hbox_idvar->addWidget(label_id);
@ -265,7 +268,7 @@ CreateFigureDialog::CreateFigureDialog(QWidget* parent, u8 slot) : QDialog(paren
const auto found_fig = system.GetInfinityBase().FindFigure(char_number);
if (!found_fig.empty())
{
predef_name += QString::fromStdString(std::string(found_fig) + ".bin");
predef_name += QString::fromStdString(found_fig + ".bin");
}
else
{

View file

@ -1,19 +1,24 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <string>
#include <QDialog>
#include <QVBoxLayout>
#include <QWidget>
#include "Core/Core.h"
#include "Core/IOS/USB/Emulated/Infinity.h"
#include "Common/CommonTypes.h"
class QCheckBox;
class QGroupBox;
class QLineEdit;
class QVBoxLayout;
namespace Core
{
enum class State;
}
class InfinityBaseWindow : public QWidget
{

View file

@ -125,7 +125,7 @@ int main(int argc, char* argv[])
}
#endif
Host::GetInstance()->DeclareAsHostThread();
Core::DeclareAsHostThread();
#ifdef __APPLE__
// On macOS, a command line option matching the format "-psn_X_XXXXXX" is passed when
@ -149,15 +149,6 @@ int main(int argc, char* argv[])
#endif
#endif
// setHighDpiScaleFactorRoundingPolicy was added in 5.14, but default behavior changed in 6.0
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
// Set to the previous default behavior
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
#else
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
QCoreApplication::setOrganizationName(QStringLiteral("Dolphin Emulator"));
QCoreApplication::setOrganizationDomain(QStringLiteral("dolphin-emu.org"));
QCoreApplication::setApplicationName(QStringLiteral("dolphin-emu"));

View file

@ -72,6 +72,7 @@
#include "DiscIO/RiivolutionPatcher.h"
#include "DolphinQt/AboutDialog.h"
#include "DolphinQt/Achievements/AchievementsWindow.h"
#include "DolphinQt/CheatsManager.h"
#include "DolphinQt/Config/ControllersWindow.h"
#include "DolphinQt/Config/FreeLookWindow.h"
@ -342,12 +343,17 @@ MainWindow::~MainWindow()
Config::Save();
}
WindowSystemInfo MainWindow::GetWindowSystemInfo() const
{
return ::GetWindowSystemInfo(m_render_widget->windowHandle());
}
void MainWindow::InitControllers()
{
if (g_controller_interface.IsInit())
return;
UICommon::InitControllers(GetWindowSystemInfo(windowHandle()));
UICommon::InitControllers(::GetWindowSystemInfo(windowHandle()));
m_hotkey_scheduler = new HotkeyScheduler();
m_hotkey_scheduler->Start();
@ -542,6 +548,10 @@ void MainWindow::ConnectMenuBar()
connect(m_menu_bar, &MenuBar::ShowInfinityBase, this, &MainWindow::ShowInfinityBase);
connect(m_menu_bar, &MenuBar::ConnectWiiRemote, this, &MainWindow::OnConnectWiiRemote);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(m_menu_bar, &MenuBar::ShowAchievementsWindow, this, &MainWindow::ShowAchievementsWindow);
#endif // USE_RETRO_ACHIEVEMENTS
// Movie
connect(m_menu_bar, &MenuBar::PlayRecording, this, &MainWindow::OnPlayRecording);
connect(m_menu_bar, &MenuBar::StartRecording, this, &MainWindow::OnStartRecording);
@ -640,6 +650,11 @@ void MainWindow::ConnectHotkeys()
&CodeWidget::ToggleBreakpoint);
connect(m_hotkey_scheduler, &HotkeyScheduler::AddBreakpoint, m_code_widget,
&CodeWidget::AddBreakpoint);
connect(m_hotkey_scheduler, &HotkeyScheduler::SkylandersPortalHotkey, this,
&MainWindow::ShowSkylanderPortal);
connect(m_hotkey_scheduler, &HotkeyScheduler::InfinityBaseHotkey, this,
&MainWindow::ShowInfinityBase);
}
void MainWindow::ConnectToolBar()
@ -1192,7 +1207,7 @@ void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
// Boot up, show an error if it fails to load the game.
if (!BootManager::BootCore(std::move(parameters),
GetWindowSystemInfo(m_render_widget->windowHandle())))
::GetWindowSystemInfo(m_render_widget->windowHandle())))
{
ModalMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok);
HideRenderWidget();
@ -1300,7 +1315,7 @@ void MainWindow::HideRenderWidget(bool reinit, bool is_exit)
// The controller interface will still be registered to the old render widget, if the core
// has booted. Therefore, we should re-bind it to the main window for now. When the core
// is next started, it will be swapped back to the new render widget.
g_controller_interface.ChangeWindow(GetWindowSystemInfo(windowHandle()).render_window,
g_controller_interface.ChangeWindow(::GetWindowSystemInfo(windowHandle()).render_window,
is_exit ? ControllerInterface::WindowChangeReason::Exit :
ControllerInterface::WindowChangeReason::Other);
}
@ -1992,6 +2007,20 @@ void MainWindow::OnConnectWiiRemote(int id)
});
}
#ifdef USE_RETRO_ACHIEVEMENTS
void MainWindow::ShowAchievementsWindow()
{
if (!m_achievements_window)
{
m_achievements_window = new AchievementsWindow(this);
}
m_achievements_window->show();
m_achievements_window->raise();
m_achievements_window->activateWindow();
}
#endif // USE_RETRO_ACHIEVEMENTS
void MainWindow::ShowMemcardManager()
{
GCMemcardManager manager(this);

View file

@ -16,6 +16,7 @@
class QStackedWidget;
class QString;
class AchievementsWindow;
class BreakpointWidget;
struct BootParameters;
class CheatsManager;
@ -49,6 +50,7 @@ class ThreadWidget;
class ToolBar;
class WatchWidget;
class WiiTASInputWindow;
struct WindowSystemInfo;
namespace DiscIO
{
@ -75,6 +77,7 @@ public:
~MainWindow();
void Show();
WindowSystemInfo GetWindowSystemInfo() const;
bool eventFilter(QObject* object, QEvent* event) override;
@ -169,6 +172,10 @@ private:
void ShowCheatsManager();
void ShowRiivolutionBootWidget(const UICommon::GameFile& game);
#ifdef USE_RETRO_ACHIEVEMENTS
void ShowAchievementsWindow();
#endif // USE_RETRO_ACHIEVEMENTS
void NetPlayInit();
bool NetPlayJoin();
bool NetPlayHost(const UICommon::GameFile& game);
@ -242,6 +249,10 @@ private:
static constexpr int num_wii_controllers = 4;
std::array<WiiTASInputWindow*, num_wii_controllers> m_wii_tas_input_windows{};
#ifdef USE_RETRO_ACHIEVEMENTS
AchievementsWindow* m_achievements_window = nullptr;
#endif // USE_RETRO_ACHIEVEMENTS
BreakpointWidget* m_breakpoint_widget;
CodeWidget* m_code_widget;
JITWidget* m_jit_widget;

View file

@ -21,6 +21,7 @@
#include "Core/Boot/Boot.h"
#include "Core/CommonTitles.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
@ -232,6 +233,19 @@ void MenuBar::AddToolsMenu()
tools_menu->addSeparator();
tools_menu->addAction(tr("Start &NetPlay..."), this, &MenuBar::StartNetPlay);
tools_menu->addSeparator();
#ifdef USE_RETRO_ACHIEVEMENTS
if (Config::Get(Config::RA_ENABLED))
{
tools_menu->addAction(tr("Achievements"), this, [this] { emit ShowAchievementsWindow(); });
tools_menu->addSeparator();
}
#endif // USE_RETRO_ACHIEVEMENTS
QMenu* gc_ipl = tools_menu->addMenu(tr("Load GameCube Main Menu"));
m_ntscj_ipl = gc_ipl->addAction(tr("NTSC-J"), this,

View file

@ -93,6 +93,10 @@ signals:
void ShowInfinityBase();
void ConnectWiiRemote(int id);
#ifdef USE_RETRO_ACHIEVEMENTS
void ShowAchievementsWindow();
#endif // USE_RETRO_ACHIEVEMENTS
// Options
void Configure();
void ConfigureGraphics();

View file

@ -45,7 +45,7 @@ public:
void SetValue(int progress) { emit SetValueSignal(progress); }
// Can be called from any thread
bool WasCanceled() { return m_was_cancelled.IsSet(); }
bool WasCanceled() const { return m_was_cancelled.IsSet(); }
signals:
void CancelSignal();
@ -126,6 +126,6 @@ private:
QProgressDialog m_dialog;
Common::Flag m_was_cancelled;
int m_last_received_progress;
int m_last_received_progress = 0;
bool m_is_setting_value = false;
};

View file

@ -437,6 +437,10 @@ bool RenderWidget::event(QEvent* event)
case QEvent::Move:
SetCursorLocked(m_cursor_locked);
break;
// According to https://bugreports.qt.io/browse/QTBUG-95925 the recommended practice for
// handling DPI change is responding to paint events
case QEvent::Paint:
case QEvent::Resize:
{
SetCursorLocked(m_cursor_locked);
@ -446,9 +450,18 @@ bool RenderWidget::event(QEvent* event)
QScreen* screen = window()->windowHandle()->screen();
const auto dpr = screen->devicePixelRatio();
const float dpr = screen->devicePixelRatio();
const int width = new_size.width() * dpr;
const int height = new_size.height() * dpr;
emit SizeChanged(new_size.width() * dpr, new_size.height() * dpr);
if (m_last_window_width != width || m_last_window_height != height ||
m_last_window_scale != dpr)
{
m_last_window_width = width;
m_last_window_height = height;
m_last_window_scale = dpr;
emit SizeChanged(width, height);
}
break;
}
// Happens when we add/remove the widget from the main window instead of the dedicated one

View file

@ -47,6 +47,9 @@ private:
static constexpr int MOUSE_HIDE_DELAY = 3000;
QTimer* m_mouse_timer;
QPoint m_last_mouse{};
int m_last_window_width = 0;
int m_last_window_height = 0;
float m_last_window_scale = 0;
bool m_cursor_locked = false;
bool m_lock_cursor_on_next_activation = false;
bool m_dont_lock_cursor_on_show = false;

View file

@ -71,7 +71,7 @@ Settings::Settings()
});
m_hotplug_callback_handle = g_controller_interface.RegisterDevicesChangedCallback([this] {
if (Host::GetInstance()->IsHostThread())
if (Core::IsHostThread())
{
emit DevicesChanged();
}

View file

@ -100,7 +100,9 @@ void BroadbandAdapterSettingsDialog::SaveAddress()
switch (m_bba_type)
{
case Type::Ethernet:
if (!std::regex_match(bba_new_address, std::regex("([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})")))
{
static const std::regex re_mac_address("([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})");
if (!std::regex_match(bba_new_address, re_mac_address))
{
ModalMessageBox::critical(
this, tr("Broadband Adapter Error"),
@ -111,7 +113,7 @@ void BroadbandAdapterSettingsDialog::SaveAddress()
}
Config::SetBaseOrCurrent(Config::MAIN_BBA_MAC, bba_new_address);
break;
}
case Type::BuiltIn:
Config::SetBaseOrCurrent(Config::MAIN_BBA_BUILTIN_DNS, bba_new_address);
break;

View file

@ -3,7 +3,9 @@
#include "DolphinQt/Settings/WiiPane.h"
#include <array>
#include <future>
#include <utility>
#include <QCheckBox>
#include <QComboBox>
@ -53,6 +55,36 @@ static int TranslateSensorBarPosition(int position)
return position;
}
namespace
{
struct SDSizeComboEntry
{
u64 size;
const char* name;
};
static constexpr u64 MebibytesToBytes(u64 mebibytes)
{
return mebibytes * 1024u * 1024u;
}
static constexpr u64 GibibytesToBytes(u64 gibibytes)
{
return MebibytesToBytes(gibibytes * 1024u);
}
constexpr std::array sd_size_combo_entries{
SDSizeComboEntry{0, _trans("Auto")},
SDSizeComboEntry{MebibytesToBytes(64), _trans("64 MiB")},
SDSizeComboEntry{MebibytesToBytes(128), _trans("128 MiB")},
SDSizeComboEntry{MebibytesToBytes(256), _trans("256 MiB")},
SDSizeComboEntry{MebibytesToBytes(512), _trans("512 MiB")},
SDSizeComboEntry{GibibytesToBytes(1), _trans("1 GiB")},
SDSizeComboEntry{GibibytesToBytes(2), _trans("2 GiB")},
SDSizeComboEntry{GibibytesToBytes(4), _trans("4 GiB (SDHC)")},
SDSizeComboEntry{GibibytesToBytes(8), _trans("8 GiB (SDHC)")},
SDSizeComboEntry{GibibytesToBytes(16), _trans("16 GiB (SDHC)")},
SDSizeComboEntry{GibibytesToBytes(32), _trans("32 GiB (SDHC)")},
};
} // namespace
WiiPane::WiiPane(QWidget* parent) : QWidget(parent)
{
CreateLayout();
@ -94,6 +126,8 @@ void WiiPane::ConnectLayout()
connect(m_sd_card_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig);
connect(m_allow_sd_writes_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig);
connect(m_sync_sd_folder_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig);
connect(m_sd_card_size_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
&WiiPane::OnSaveConfig);
// Whitelisted USB Passthrough Devices
connect(m_whitelist_usb_list, &QListWidget::itemClicked, this, &WiiPane::ValidateSelectionState);
@ -219,6 +253,13 @@ void WiiPane::CreateSDCard()
++row;
}
m_sd_card_size_combo = new QComboBox();
for (size_t i = 0; i < sd_size_combo_entries.size(); ++i)
m_sd_card_size_combo->addItem(tr(sd_size_combo_entries[i].name));
sd_settings_group_layout->addWidget(new QLabel(tr("SD Card File Size:")), row, 0);
sd_settings_group_layout->addWidget(m_sd_card_size_combo, row, 1);
++row;
m_sd_pack_button = new NonDefaultQPushButton(tr("Convert Folder to File Now"));
m_sd_unpack_button = new NonDefaultQPushButton(tr("Convert File to Folder Now"));
connect(m_sd_pack_button, &QPushButton::clicked, [this] {
@ -360,6 +401,13 @@ void WiiPane::LoadConfig()
m_allow_sd_writes_checkbox->setChecked(Config::Get(Config::MAIN_ALLOW_SD_WRITES));
m_sync_sd_folder_checkbox->setChecked(Config::Get(Config::MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC));
const u64 sd_card_size = Config::Get(Config::MAIN_WII_SD_CARD_FILESIZE);
for (size_t i = 0; i < sd_size_combo_entries.size(); ++i)
{
if (sd_size_combo_entries[i].size == sd_card_size)
m_sd_card_size_combo->setCurrentIndex(static_cast<int>(i));
}
PopulateUSBPassthroughListWidget();
m_wiimote_ir_sensor_position->setCurrentIndex(
@ -390,6 +438,14 @@ void WiiPane::OnSaveConfig()
Config::SetBase(Config::MAIN_ALLOW_SD_WRITES, m_allow_sd_writes_checkbox->isChecked());
Config::SetBase(Config::MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC,
m_sync_sd_folder_checkbox->isChecked());
const int sd_card_size_index = m_sd_card_size_combo->currentIndex();
if (sd_card_size_index >= 0 &&
static_cast<size_t>(sd_card_size_index) < sd_size_combo_entries.size())
{
Config::SetBase(Config::MAIN_WII_SD_CARD_FILESIZE,
sd_size_combo_entries[sd_card_size_index].size);
}
}
void WiiPane::ValidateSelectionState()

View file

@ -62,6 +62,7 @@ private:
QCheckBox* m_sd_card_checkbox;
QCheckBox* m_allow_sd_writes_checkbox;
QCheckBox* m_sync_sd_folder_checkbox;
QComboBox* m_sd_card_size_combo;
QLineEdit* m_sd_raw_edit;
QLineEdit* m_sd_sync_folder_edit;
QPushButton* m_sd_pack_button;

View file

@ -6,8 +6,11 @@
#include <array>
#include <optional>
#include <QDialog>
#include <QBrush>
#include <QFrame>
#include <QString>
#include <QTimer>
#include <QVBoxLayout>
#include <QWidget>
#include "Core/Core.h"
@ -16,12 +19,15 @@
class QCheckBox;
class QGroupBox;
class QLineEdit;
class QPushButton;
class QRadioButton;
class QListWidget;
struct Skylander
{
u8 portal_slot;
u16 sky_id;
u16 sky_var;
u16 m_sky_id;
u16 m_sky_var;
};
class SkylanderPortalWindow : public QWidget
@ -36,29 +42,58 @@ protected:
std::array<std::optional<Skylander>, MAX_SKYLANDERS> m_sky_slots;
private:
// Window
void CreateMainWindow();
void OnEmulationStateChanged(Core::State state);
void CreateSkylander(u8 slot);
void ClearSkylander(u8 slot);
void EmulatePortal(bool emulate);
void LoadSkylander(u8 slot);
void LoadSkylanderPath(u8 slot, const QString& path);
void UpdateEdits();
QVBoxLayout* CreateSlotLayout();
QVBoxLayout* CreateFinderLayout();
void closeEvent(QCloseEvent* bar) override;
bool eventFilter(QObject* object, QEvent* event) final override;
QCheckBox* m_checkbox;
QGroupBox* m_group_skylanders;
};
class CreateSkylanderDialog : public QDialog
{
Q_OBJECT
public:
explicit CreateSkylanderDialog(QWidget* parent);
QString GetFilePath() const;
protected:
QString m_file_path;
// UI
void EmulatePortal(bool emulate);
void SelectCollectionPath();
void LoadSelected();
void LoadFromFile();
void ClearSlot(u8 slot);
void CreateSkylanderAdvanced();
// Behind the scenes
void OnEmulationStateChanged(Core::State state);
void OnCollectionPathChanged();
void RefreshList();
void UpdateCurrentIDs();
void CreateSkyfile(const QString& path, bool load_after);
void LoadSkyfilePath(u8 slot, const QString& path);
void UpdateSlotNames();
// Helpers
bool PassesFilter(QString name, u16 id, u16 var);
QString GetFilePath(u16 id, u16 var);
u8 GetCurrentSlot();
int GetElementRadio();
QBrush GetBaseColor(std::pair<const u16, const u16> ids);
int GetGameID(IOS::HLE::USB::Game game);
int GetElementID(IOS::HLE::USB::Element elem);
bool m_emulating;
QCheckBox* m_enabled_checkbox;
QFrame* m_group_skylanders;
QFrame* m_command_buttons;
std::array<QRadioButton*, 16> m_slot_radios;
// Qt is not guaranteed to keep track of file paths using native file pickers, so we use this
// variable to ensure we open at the most recent Skylander file location
QString m_last_skylander_path;
QString m_collection_path;
QLineEdit* m_path_edit;
QPushButton* m_path_select;
std::array<QCheckBox*, 5> m_game_filters;
std::array<QRadioButton*, 10> m_element_filter;
QCheckBox* m_only_show_collection;
QLineEdit* m_sky_search;
QListWidget* m_skylander_list;
u16 m_sky_id = 0;
u16 m_sky_var = 0;
};