diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 47df65334b..2412609804 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -362,6 +362,8 @@ add_executable(dolphin-emu Settings/GeneralPane.h Settings/InterfacePane.cpp Settings/InterfacePane.h + Settings/OnScreenDisplayPane.cpp + Settings/OnScreenDisplayPane.h Settings/PathPane.cpp Settings/PathPane.h Settings/USBDevicePicker.cpp diff --git a/Source/Core/DolphinQt/Config/SettingsWindow.cpp b/Source/Core/DolphinQt/Config/SettingsWindow.cpp index a1279c5eb5..8efae30cee 100644 --- a/Source/Core/DolphinQt/Config/SettingsWindow.cpp +++ b/Source/Core/DolphinQt/Config/SettingsWindow.cpp @@ -22,6 +22,7 @@ #include "DolphinQt/Settings/GameCubePane.h" #include "DolphinQt/Settings/GeneralPane.h" #include "DolphinQt/Settings/InterfacePane.h" +#include "DolphinQt/Settings/OnScreenDisplayPane.h" #include "DolphinQt/Settings/PathPane.h" #include "DolphinQt/Settings/WiiPane.h" @@ -129,6 +130,7 @@ SettingsWindow::SettingsWindow(MainWindow* parent) : StackedSettingsWindow{paren AddPane(new GraphicsPane{parent, nullptr}, tr("Graphics")); AddWrappedPane(new ControllersPane, tr("Controllers")); AddWrappedPane(new InterfacePane, tr("Interface")); + AddWrappedPane(new OnScreenDisplayPane, tr("On-Screen Display")); AddWrappedPane(new AudioPane, tr("Audio")); AddWrappedPane(new PathPane, tr("Paths")); AddWrappedPane(new GameCubePane, tr("GameCube")); diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index 596de91a53..eb548ae0ad 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -218,6 +218,7 @@ + @@ -268,6 +269,7 @@ + diff --git a/Source/Core/DolphinQt/Settings/OnScreenDisplayPane.cpp b/Source/Core/DolphinQt/Settings/OnScreenDisplayPane.cpp new file mode 100644 index 0000000000..5076eba710 --- /dev/null +++ b/Source/Core/DolphinQt/Settings/OnScreenDisplayPane.cpp @@ -0,0 +1,248 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "DolphinQt/Settings/OnScreenDisplayPane.h" + +#include +#include +#include +#include +#include + +#include "Core/Config/GraphicsSettings.h" +#include "Core/Config/MainSettings.h" + +#include "DolphinQt/Config/ConfigControls/ConfigBool.h" +#include "DolphinQt/Config/ConfigControls/ConfigInteger.h" + +OnScreenDisplayPane::OnScreenDisplayPane(QWidget* parent) : QWidget(parent) +{ + CreateLayout(); + ConnectLayout(); + AddDescriptions(); +} + +void OnScreenDisplayPane::CreateLayout() +{ + // General + auto* general_box = new QGroupBox(tr("General")); + auto* general_layout = new QGridLayout(); + general_box->setLayout(general_layout); + + m_enable_osd = new ConfigBool(tr("Show Messages"), Config::MAIN_OSD_MESSAGES); + m_font_size = new ConfigInteger(12, 40, Config::MAIN_OSD_FONT_SIZE); + + general_layout->addWidget(m_enable_osd, 0, 0); + general_layout->addWidget(new QLabel(tr("Font Size:")), 1, 0); + general_layout->addWidget(m_font_size, 1, 1); + + // Performance + auto* performance_box = new QGroupBox(tr("Performance Statistics")); + auto* performance_layout = new QGridLayout(); + performance_box->setLayout(performance_layout); + + m_show_fps = new ConfigBool(tr("Show FPS"), Config::GFX_SHOW_FPS); + m_show_ftimes = new ConfigBool(tr("Show Frame Times"), Config::GFX_SHOW_FTIMES); + m_show_vps = new ConfigBool(tr("Show VPS"), Config::GFX_SHOW_VPS); + m_show_vtimes = new ConfigBool(tr("Show VBlank Times"), Config::GFX_SHOW_VTIMES); + m_show_speed = new ConfigBool(tr("Show % Speed"), Config::GFX_SHOW_SPEED); + m_speed_colors = new ConfigBool(tr("Show Speed Colors"), Config::GFX_SHOW_SPEED_COLORS); + m_show_graph = new ConfigBool(tr("Show Performance Graphs"), Config::GFX_SHOW_GRAPHS); + m_graph_update_label = new QLabel(tr("Graph Update Rate (ms):")); + m_graph_update_rate = new ConfigInteger(0, 10000, Config::GFX_PERF_SAMP_WINDOW, 100); + m_graph_update_rate->SetTitle(tr("Performance Sample Window (ms)")); + + performance_layout->addWidget(m_show_fps, 0, 0); + performance_layout->addWidget(m_show_ftimes, 0, 1); + performance_layout->addWidget(m_show_vps, 1, 0); + performance_layout->addWidget(m_show_vtimes, 1, 1); + performance_layout->addWidget(m_show_speed, 2, 0); + performance_layout->addWidget(m_speed_colors, 2, 1); + performance_layout->addWidget(m_show_graph, 3, 0); + performance_layout->addWidget(m_graph_update_label, 4, 0); + performance_layout->addWidget(m_graph_update_rate, 4, 1); + + // Movie + auto* movie_box = new QGroupBox(tr("Movie Window")); + auto* movie_layout = new QGridLayout(); + movie_box->setLayout(movie_layout); + + m_rerecord_counter = + new ConfigBool(tr("Show Rerecord Counter"), Config::MAIN_MOVIE_SHOW_RERECORD); + m_lag_counter = new ConfigBool(tr("Show Lag Counter"), Config::MAIN_SHOW_LAG); + m_frame_counter = new ConfigBool(tr("Show Frame Counter"), Config::MAIN_SHOW_FRAME_COUNT); + m_input_display = new ConfigBool(tr("Show Input Display"), Config::MAIN_MOVIE_SHOW_INPUT_DISPLAY); + m_system_clock = new ConfigBool(tr("Show System Clock"), Config::MAIN_MOVIE_SHOW_RTC); + + movie_layout->addWidget(m_rerecord_counter, 0, 0); + movie_layout->addWidget(m_lag_counter, 0, 1); + movie_layout->addWidget(m_frame_counter, 1, 0); + movie_layout->addWidget(m_input_display, 1, 1); + movie_layout->addWidget(m_system_clock, 2, 0); + + // NetPlay + auto* netplay_box = new QGroupBox(tr("Netplay")); + auto* netplay_layout = new QGridLayout(); + netplay_box->setLayout(netplay_layout); + + m_show_ping = new ConfigBool(tr("Show NetPlay Ping"), Config::GFX_SHOW_NETPLAY_PING); + m_show_chat = new ConfigBool(tr("Show NetPlay Chat"), Config::GFX_SHOW_NETPLAY_MESSAGES); + + netplay_layout->addWidget(m_show_ping, 0, 0); + netplay_layout->addWidget(m_show_chat, 0, 1); + + // Debug + auto* debug_box = new QGroupBox(tr("Debug")); + auto* debug_layout = new QGridLayout(); + debug_box->setLayout(debug_layout); + + m_show_statistics = new ConfigBool(tr("Show Statistics"), Config::GFX_OVERLAY_STATS); + m_show_proj_statistics = + new ConfigBool(tr("Show Projection Statistics"), Config::GFX_OVERLAY_PROJ_STATS); + + debug_layout->addWidget(m_show_statistics, 0, 0); + debug_layout->addWidget(m_show_proj_statistics, 0, 1); + + // Stack GroupBoxes + auto* main_layout = new QVBoxLayout; + main_layout->addWidget(general_box); + main_layout->addWidget(performance_box); + main_layout->addWidget(movie_box); + main_layout->addWidget(netplay_box); + main_layout->addWidget(debug_box); + main_layout->addStretch(); + setLayout(main_layout); +} + +void OnScreenDisplayPane::ConnectLayout() +{ + // Disable graph options when graph is not visible. + m_graph_update_rate->setEnabled(m_show_graph->isChecked()); + m_graph_update_label->setEnabled(m_show_graph->isChecked()); + connect(m_show_graph, &QCheckBox::toggled, this, [this](bool checked) { + m_graph_update_rate->setEnabled(checked); + m_graph_update_label->setEnabled(checked); + }); + + // Disable movie window options when window is closed. + auto enable_movie_items = [this](bool checked) { + for (auto* widget : + {m_rerecord_counter, m_frame_counter, m_lag_counter, m_system_clock, m_input_display}) + { + widget->setEnabled(checked); + } + }; + + enable_movie_items(m_movie_window->isChecked()); + connect(m_movie_window, &QCheckBox::toggled, this, [this, enable_movie_items](bool checked) { + enable_movie_items(m_movie_window->isChecked()); + }); +} + +void OnScreenDisplayPane::AddDescriptions() +{ + static constexpr char TR_ENABLE_OSD_DESCRIPTION[] = + QT_TR_NOOP("Shows on-screen display messages over the render window. These messages " + "disappear after several seconds." + "

If unsure, leave this checked."); + static const char TR_OSD_FONT_SIZE_DESCRIPTION[] = QT_TR_NOOP( + "Changes the font size of the On-Screen Display. Affects features such as performance " + "statistics, frame counter, and netplay chat.

If " + "unsure, leave this at 13."); + + static const char TR_SHOW_FPS_DESCRIPTION[] = + QT_TR_NOOP("Shows the number of distinct frames rendered per second as a measure of " + "visual smoothness.

If unsure, leave this " + "unchecked."); + static const char TR_SHOW_FTIMES_DESCRIPTION[] = + QT_TR_NOOP("Shows the average time in ms between each distinct rendered frame alongside " + "the standard deviation.

If unsure, leave this " + "unchecked."); + static const char TR_SHOW_VPS_DESCRIPTION[] = + QT_TR_NOOP("Shows the number of frames rendered per second as a measure of " + "emulation speed.

If unsure, leave this " + "unchecked."); + static const char TR_SHOW_VTIMES_DESCRIPTION[] = + QT_TR_NOOP("Shows the average time in ms between each rendered frame alongside " + "the standard deviation.

If unsure, leave this " + "unchecked."); + static const char TR_SHOW_GRAPHS_DESCRIPTION[] = + QT_TR_NOOP("Shows frametime graph along with statistics as a representation of " + "emulation performance.

If unsure, leave this " + "unchecked."); + static const char TR_SHOW_SPEED_DESCRIPTION[] = + QT_TR_NOOP("Shows the % speed of emulation compared to full speed." + "

If unsure, leave this " + "unchecked."); + static const char TR_SHOW_SPEED_COLORS_DESCRIPTION[] = + QT_TR_NOOP("Changes the color of the FPS counter depending on emulation speed." + "

If unsure, leave this " + "checked."); + static const char TR_PERF_SAMP_WINDOW_DESCRIPTION[] = + QT_TR_NOOP("The amount of time the FPS and VPS counters will sample over." + "

The higher the value, the more stable the FPS/VPS counter will be, " + "but the slower it will be to update." + "

If unsure, leave this " + "at 1000ms."); + static const char TR_LOG_RENDERTIME_DESCRIPTION[] = QT_TR_NOOP( + "Logs the render time of every frame to User/Logs/render_time.txt.

Use this " + "feature to measure Dolphin's performance.

If " + "unsure, leave this unchecked."); + + static const char TR_SHOW_NETPLAY_PING_DESCRIPTION[] = QT_TR_NOOP( + "Shows the player's maximum ping while playing on " + "NetPlay.

If unsure, leave this unchecked."); + static const char TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION[] = + QT_TR_NOOP("Shows chat messages, buffer changes, and desync alerts " + "while playing NetPlay.

If unsure, leave " + "this unchecked."); + + static const char TR_RERECORD_COUNTER_DESCRIPTION[] = + QT_TR_NOOP("Shows how many times the input recording has been overwritten by using " + "savestates.

If unsure, leave " + "this unchecked."); + static const char TR_LAG_COUNTER_DESCRIPTION[] = QT_TR_NOOP( + "Shows how many frames have occured without controller inputs being checked. Resets to 1 " + "when inputs are processed.

If unsure, leave " + "this unchecked."); + static const char TR_FRAME_COUNTER_DESCRIPTION[] = + QT_TR_NOOP("Shows how many frames have passed.

If unsure, leave " + "this unchecked."); + static const char TR_INPUT_DISPLAY_DESCRIPTION[] = QT_TR_NOOP( + "Shows the controls currently being input.

If unsure, leave " + "this unchecked."); + static const char TR_SYSTEM_CLOCK_DESCRIPTION[] = + QT_TR_NOOP("Shows current system time.

If unsure, leave " + "this unchecked."); + + static const char TR_SHOW_STATS_DESCRIPTION[] = + QT_TR_NOOP("Shows various rendering statistics.

If unsure, " + "leave this unchecked."); + static const char TR_SHOW_PROJ_STATS_DESCRIPTION[] = + QT_TR_NOOP("Shows various projection statistics.

If unsure, " + "leave this unchecked."); + + m_enable_osd->SetDescription(tr(TR_ENABLE_OSD_DESCRIPTION)); + m_font_size->SetDescription(tr(TR_OSD_FONT_SIZE_DESCRIPTION)); + + m_show_fps->SetDescription(tr(TR_SHOW_FPS_DESCRIPTION)); + m_show_ftimes->SetDescription(tr(TR_SHOW_FTIMES_DESCRIPTION)); + m_show_vps->SetDescription(tr(TR_SHOW_VPS_DESCRIPTION)); + m_show_vtimes->SetDescription(tr(TR_SHOW_VTIMES_DESCRIPTION)); + m_show_graph->SetDescription(tr(TR_SHOW_GRAPHS_DESCRIPTION)); + m_show_speed->SetDescription(tr(TR_SHOW_SPEED_DESCRIPTION)); + m_graph_update_rate->SetDescription(tr(TR_PERF_SAMP_WINDOW_DESCRIPTION)); + m_speed_colors->SetDescription(tr(TR_SHOW_SPEED_COLORS_DESCRIPTION)); + + m_show_ping->SetDescription(tr(TR_SHOW_NETPLAY_PING_DESCRIPTION)); + m_show_chat->SetDescription(tr(TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION)); + + m_rerecord_counter->SetDescription(tr(TR_RERECORD_COUNTER_DESCRIPTION)); + m_lag_counter->SetDescription(tr(TR_LAG_COUNTER_DESCRIPTION)); + m_frame_counter->SetDescription(tr(TR_FRAME_COUNTER_DESCRIPTION)); + m_input_display->SetDescription(tr(TR_INPUT_DISPLAY_DESCRIPTION)); + m_system_clock->SetDescription(tr(TR_SYSTEM_CLOCK_DESCRIPTION)); + + m_show_statistics->SetDescription(tr(TR_SHOW_STATS_DESCRIPTION)); + m_show_proj_statistics->SetDescription(tr(TR_SHOW_PROJ_STATS_DESCRIPTION)); +} diff --git a/Source/Core/DolphinQt/Settings/OnScreenDisplayPane.h b/Source/Core/DolphinQt/Settings/OnScreenDisplayPane.h new file mode 100644 index 0000000000..89bbadef02 --- /dev/null +++ b/Source/Core/DolphinQt/Settings/OnScreenDisplayPane.h @@ -0,0 +1,51 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +class QLabel; +class ConfigBool; +class ConfigInteger; + +class OnScreenDisplayPane final : public QWidget +{ +public: + explicit OnScreenDisplayPane(QWidget* parent = nullptr); + +private: + void CreateLayout(); + void ConnectLayout(); + void AddDescriptions(); + + // General + ConfigBool* m_enable_osd; + ConfigInteger* m_font_size; + + // Performance + ConfigBool* m_show_fps; + ConfigBool* m_show_ftimes; + ConfigBool* m_show_vps; + ConfigBool* m_show_vtimes; + ConfigBool* m_show_graph; + ConfigBool* m_show_speed; + ConfigBool* m_speed_colors; + QLabel* m_graph_update_label; + ConfigInteger* m_graph_update_rate; + + // Movie window + ConfigBool* m_rerecord_counter; + ConfigBool* m_lag_counter; + ConfigBool* m_frame_counter; + ConfigBool* m_input_display; + ConfigBool* m_system_clock; + + // Netplay + ConfigBool* m_show_ping; + ConfigBool* m_show_chat; + + // Debug + ConfigBool* m_show_statistics; + ConfigBool* m_show_proj_statistics; +};