mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-09-02 15:45:58 +00:00
Merge branch 'master' of https://github.com/dolphin-emu/dolphin into dolphin-emu-master
This commit is contained in:
commit
6280ce45a7
415 changed files with 14795 additions and 9405 deletions
239
Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp
Normal file
239
Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp
Normal 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
|
|
@ -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
|
56
Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp
Normal file
56
Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp
Normal 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
|
28
Source/Core/DolphinQt/Achievements/AchievementsWindow.h
Normal file
28
Source/Core/DolphinQt/Achievements/AchievementsWindow.h
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())));
|
||||
|
|
|
@ -28,4 +28,6 @@ signals:
|
|||
private:
|
||||
void CreateMainLayout();
|
||||
void OnBackendChanged(const QString& backend);
|
||||
|
||||
MainWindow* const m_main_window;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
39
Source/Core/DolphinQt/Config/Mapping/HotkeyUSBEmu.cpp
Normal file
39
Source/Core/DolphinQt/Config/Mapping/HotkeyUSBEmu.cpp
Normal 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();
|
||||
}
|
26
Source/Core/DolphinQt/Config/Mapping/HotkeyUSBEmu.h
Normal file
26
Source/Core/DolphinQt/Config/Mapping/HotkeyUSBEmu.h
Normal 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;
|
||||
};
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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. "
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -65,6 +65,9 @@ signals:
|
|||
void ToggleBreakpoint();
|
||||
void AddBreakpoint();
|
||||
|
||||
void SkylandersPortalHotkey();
|
||||
void InfinityBaseHotkey();
|
||||
|
||||
private:
|
||||
void Run();
|
||||
void CheckDebuggingHotkeys();
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -71,7 +71,7 @@ Settings::Settings()
|
|||
});
|
||||
|
||||
m_hotplug_callback_handle = g_controller_interface.RegisterDevicesChangedCallback([this] {
|
||||
if (Host::GetInstance()->IsHostThread())
|
||||
if (Core::IsHostThread())
|
||||
{
|
||||
emit DevicesChanged();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue