Add shortcuts and status bar widgets to toggle and set 3D factor (#6277)
This commit is contained in:
		
							
								
								
									
										2
									
								
								dist/qt_themes/colorful/style.qrc
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/qt_themes/colorful/style.qrc
									
									
									
									
										vendored
									
									
								
							| @@ -13,6 +13,6 @@ | ||||
|         <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file> | ||||
|     </qresource> | ||||
|     <qresource prefix="colorful"> | ||||
|         <file>style.qss</file> | ||||
|         <file alias="style.qss">../default/style.qss</file> | ||||
|     </qresource> | ||||
| </RCC> | ||||
|   | ||||
							
								
								
									
										4
									
								
								dist/qt_themes/colorful/style.qss
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								dist/qt_themes/colorful/style.qss
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +0,0 @@ | ||||
| /* | ||||
|     This file is intentionally left blank. | ||||
|     We do not want to apply any stylesheet for colorful, only icons. | ||||
| */ | ||||
							
								
								
									
										17
									
								
								dist/qt_themes/default/default.qrc
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								dist/qt_themes/default/default.qrc
									
									
									
									
										vendored
									
									
								
							| @@ -1,33 +1,22 @@ | ||||
| <RCC> | ||||
|     <qresource prefix="icons/default"> | ||||
|         <file alias="index.theme">icons/index.theme</file> | ||||
|        | ||||
|         <file alias="16x16/checked.png">icons/16x16/checked.png</file> | ||||
|  | ||||
|         <file alias="16x16/failed.png">icons/16x16/failed.png</file> | ||||
|  | ||||
|         <file alias="16x16/connected.png">icons/16x16/connected.png</file> | ||||
|  | ||||
|         <file alias="16x16/disconnected.png">icons/16x16/disconnected.png</file> | ||||
|  | ||||
|         <file alias="16x16/connected_notification.png">icons/16x16/connected_notification.png</file> | ||||
|  | ||||
|         <file alias="16x16/lock.png">icons/16x16/lock.png</file> | ||||
|  | ||||
|         <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> | ||||
|        | ||||
|         <file alias="48x48/chip.png">icons/48x48/chip.png</file> | ||||
|  | ||||
|         <file alias="48x48/folder.png">icons/48x48/folder.png</file> | ||||
|  | ||||
|         <file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file> | ||||
|  | ||||
|         <file alias="48x48/plus.png">icons/48x48/plus.png</file> | ||||
|        | ||||
|         <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file> | ||||
|        | ||||
|         <file alias="256x256/citra.png">icons/256x256/citra.png</file> | ||||
|  | ||||
|         <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file> | ||||
|     </qresource> | ||||
|     <qresource prefix="default"> | ||||
|         <file>style.qss</file> | ||||
|     </qresource> | ||||
| </RCC> | ||||
|   | ||||
							
								
								
									
										14
									
								
								dist/qt_themes/default/style.qss
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								dist/qt_themes/default/style.qss
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| QPushButton#3DOptionStatusBarButton { | ||||
|     color: #A5A5A5; | ||||
|     font-weight: bold; | ||||
|     border: 1px solid transparent; | ||||
|     background-color: transparent; | ||||
|     padding: 0px 3px 0px 3px; | ||||
|     text-align: center; | ||||
|     min-width: 60px; | ||||
|     min-height: 20px; | ||||
| } | ||||
|  | ||||
| QPushButton#3DOptionStatusBarButton:hover { | ||||
|     border: 1px solid #76797C; | ||||
| } | ||||
							
								
								
									
										22
									
								
								dist/qt_themes/qdarkstyle/style.qss
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								dist/qt_themes/qdarkstyle/style.qss
									
									
									
									
										vendored
									
									
								
							| @@ -522,13 +522,12 @@ QToolButton#qt_toolbar_ext_button { | ||||
|  | ||||
| QPushButton { | ||||
|     color: #eff0f1; | ||||
|     border-width: 1px; | ||||
|     border-color: #54575B; | ||||
|     border-style: solid; | ||||
|     padding: 6px 4px; | ||||
|     border: 1px solid #54575B; | ||||
|     border-radius: 2px; | ||||
|     padding: 5px 0px 5px 0px; | ||||
|     outline: none; | ||||
|     min-width: 100px; | ||||
|     min-height: 13px; | ||||
|     background-color: #232629; | ||||
| } | ||||
|  | ||||
| @@ -1237,3 +1236,18 @@ QPlainTextEdit:disabled { | ||||
| TouchScreenPreview { | ||||
|     qproperty-dotHighlightColor: #3daee9; | ||||
| } | ||||
|  | ||||
| QPushButton#3DOptionStatusBarButton { | ||||
|     color: #A5A5A5; | ||||
|     font-weight: bold; | ||||
|     border: 1px solid transparent; | ||||
|     background-color: transparent; | ||||
|     padding: 0px 3px 0px 3px; | ||||
|     text-align: center; | ||||
|     min-width: 60px; | ||||
|     min-height: 20px; | ||||
| } | ||||
|  | ||||
| QPushButton#3DOptionStatusBarButton:hover { | ||||
|     border: 1px solid #76797C; | ||||
| } | ||||
|   | ||||
| @@ -55,14 +55,16 @@ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config: | ||||
| // This must be in alphabetical order according to action name as it must have the same order as | ||||
| // UISetting::values.shortcuts, which is alphabetically ordered. | ||||
| // clang-format off | ||||
| const std::array<UISettings::Shortcut, 24> Config::default_hotkeys {{ | ||||
| const std::array<UISettings::Shortcut, 27> Config::default_hotkeys {{ | ||||
|      {QStringLiteral("Advance Frame"),            QStringLiteral("Main Window"), {QStringLiteral(""),     Qt::ApplicationShortcut}}, | ||||
|      {QStringLiteral("Capture Screenshot"),       QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::WidgetWithChildrenShortcut}}, | ||||
|      {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"),     Qt::WindowShortcut}}, | ||||
|      {QStringLiteral("Decrease 3D Factor"),       QStringLiteral("Main Window"), {QStringLiteral("Ctrl+-"), Qt::ApplicationShortcut}}, | ||||
|      {QStringLiteral("Decrease Speed Limit"),     QStringLiteral("Main Window"), {QStringLiteral("-"),      Qt::ApplicationShortcut}}, | ||||
|      {QStringLiteral("Exit Citra"),               QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Q"), Qt::WindowShortcut}}, | ||||
|      {QStringLiteral("Exit Fullscreen"),          QStringLiteral("Main Window"), {QStringLiteral("Esc"),    Qt::WindowShortcut}}, | ||||
|      {QStringLiteral("Fullscreen"),               QStringLiteral("Main Window"), {QStringLiteral("F11"),    Qt::WindowShortcut}}, | ||||
|      {QStringLiteral("Increase 3D Factor"),       QStringLiteral("Main Window"), {QStringLiteral("Ctrl++"), Qt::ApplicationShortcut}}, | ||||
|      {QStringLiteral("Increase Speed Limit"),     QStringLiteral("Main Window"), {QStringLiteral("+"),      Qt::ApplicationShortcut}}, | ||||
|      {QStringLiteral("Load Amiibo"),              QStringLiteral("Main Window"), {QStringLiteral("F2"),     Qt::WidgetWithChildrenShortcut}}, | ||||
|      {QStringLiteral("Load File"),                QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WidgetWithChildrenShortcut}}, | ||||
| @@ -74,6 +76,7 @@ const std::array<UISettings::Shortcut, 24> Config::default_hotkeys {{ | ||||
|      {QStringLiteral("Save to Oldest Slot"),      QStringLiteral("Main Window"), {QStringLiteral("Ctrl+C"), Qt::WindowShortcut}}, | ||||
|      {QStringLiteral("Stop Emulation"),           QStringLiteral("Main Window"), {QStringLiteral("F5"),     Qt::WindowShortcut}}, | ||||
|      {QStringLiteral("Swap Screens"),             QStringLiteral("Main Window"), {QStringLiteral("F9"),     Qt::WindowShortcut}}, | ||||
|      {QStringLiteral("Toggle 3D"),                QStringLiteral("Main Window"), {QStringLiteral("Ctrl+3"), Qt::ApplicationShortcut}}, | ||||
|      {QStringLiteral("Toggle Per-Game Speed"),    QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}}, | ||||
|      {QStringLiteral("Toggle Filter Bar"),        QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}}, | ||||
|      {QStringLiteral("Toggle Frame Advancing"),   QStringLiteral("Main Window"), {QStringLiteral("Ctrl+A"), Qt::ApplicationShortcut}}, | ||||
|   | ||||
| @@ -26,7 +26,7 @@ public: | ||||
|  | ||||
|     static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; | ||||
|     static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs; | ||||
|     static const std::array<UISettings::Shortcut, 24> default_hotkeys; | ||||
|     static const std::array<UISettings::Shortcut, 27> default_hotkeys; | ||||
|  | ||||
| private: | ||||
|     void Initialize(const std::string& config_name); | ||||
|   | ||||
| @@ -117,6 +117,7 @@ __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; | ||||
| #endif | ||||
|  | ||||
| constexpr int default_mouse_timeout = 2500; | ||||
| constexpr int num_options_3d = 5; | ||||
|  | ||||
| /** | ||||
|  * "Callouts" are one-time instructional messages shown to the user. In the config settings, there | ||||
| @@ -202,6 +203,7 @@ GMainWindow::GMainWindow() | ||||
|  | ||||
|     ConnectMenuEvents(); | ||||
|     ConnectWidgetEvents(); | ||||
|     Connect3DStateEvents(); | ||||
|  | ||||
|     LOG_INFO(Frontend, "Citra Version: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, | ||||
|              Common::g_scm_desc); | ||||
| @@ -299,7 +301,6 @@ void GMainWindow::InitializeWidgets() { | ||||
|     // Create status bar | ||||
|     message_label = new QLabel(); | ||||
|     // Configured separately for left alignment | ||||
|     message_label->setVisible(false); | ||||
|     message_label->setFrameStyle(QFrame::NoFrame); | ||||
|     message_label->setContentsMargins(4, 0, 4, 0); | ||||
|     message_label->setAlignment(Qt::AlignLeft); | ||||
| @@ -324,10 +325,26 @@ void GMainWindow::InitializeWidgets() { | ||||
|         label->setVisible(false); | ||||
|         label->setFrameStyle(QFrame::NoFrame); | ||||
|         label->setContentsMargins(4, 0, 4, 0); | ||||
|         statusBar()->addPermanentWidget(label, 0); | ||||
|         statusBar()->addPermanentWidget(label); | ||||
|     } | ||||
|     statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); | ||||
|     statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); | ||||
|  | ||||
|     option_3d_button = new QPushButton(); | ||||
|     option_3d_button->setObjectName(QStringLiteral("3DOptionStatusBarButton")); | ||||
|     option_3d_button->setFocusPolicy(Qt::NoFocus); | ||||
|     option_3d_button->setToolTip(tr("Indicates the current 3D setting. Click to toggle.")); | ||||
|  | ||||
|     factor_3d_slider = new QSlider(Qt::Orientation::Horizontal, this); | ||||
|     factor_3d_slider->setStyleSheet(QStringLiteral("QSlider { padding: 4px; }")); | ||||
|     factor_3d_slider->setToolTip(tr("Current 3D factor while 3D is enabled.")); | ||||
|     factor_3d_slider->setRange(0, 100); | ||||
|  | ||||
|     Update3DState(); | ||||
|     statusBar()->insertPermanentWidget(0, option_3d_button); | ||||
|     statusBar()->insertPermanentWidget(1, factor_3d_slider); | ||||
|  | ||||
|     statusBar()->addPermanentWidget(multiplayer_state->GetStatusText()); | ||||
|     statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon()); | ||||
|  | ||||
|     statusBar()->setVisible(true); | ||||
|  | ||||
|     // Removes an ugly inner border from the status bar widgets under Linux | ||||
| @@ -575,6 +592,35 @@ void GMainWindow::InitializeHotkeys() { | ||||
|     }); | ||||
|     connect_shortcut(QStringLiteral("Mute Audio"), | ||||
|                      [] { Settings::values.audio_muted = !Settings::values.audio_muted; }); | ||||
|  | ||||
|     connect_shortcut(QStringLiteral("Toggle 3D"), &GMainWindow::Toggle3D); | ||||
|  | ||||
|     // We use "static" here in order to avoid capturing by lambda due to a MSVC bug, which makes the | ||||
|     // variable hold a garbage value after this function exits | ||||
|     static constexpr u16 FACTOR_3D_STEP = 5; | ||||
|     connect_shortcut(QStringLiteral("Decrease 3D Factor"), [this] { | ||||
|         const auto factor_3d = Settings::values.factor_3d.GetValue(); | ||||
|         if (factor_3d > 0) { | ||||
|             if (factor_3d % FACTOR_3D_STEP != 0) { | ||||
|                 Settings::values.factor_3d = factor_3d - (factor_3d % FACTOR_3D_STEP); | ||||
|             } else { | ||||
|                 Settings::values.factor_3d = factor_3d - FACTOR_3D_STEP; | ||||
|             } | ||||
|             UpdateStatusBar(); | ||||
|         } | ||||
|     }); | ||||
|     connect_shortcut(QStringLiteral("Increase 3D Factor"), [this] { | ||||
|         const auto factor_3d = Settings::values.factor_3d.GetValue(); | ||||
|         if (factor_3d < 100) { | ||||
|             if (factor_3d % FACTOR_3D_STEP != 0) { | ||||
|                 Settings::values.factor_3d = | ||||
|                     factor_3d + FACTOR_3D_STEP - (factor_3d % FACTOR_3D_STEP); | ||||
|             } else { | ||||
|                 Settings::values.factor_3d = factor_3d + FACTOR_3D_STEP; | ||||
|             } | ||||
|             UpdateStatusBar(); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| void GMainWindow::ShowUpdaterWidgets() { | ||||
| @@ -805,6 +851,12 @@ void GMainWindow::UpdateMenuState() { | ||||
|     } | ||||
| } | ||||
|  | ||||
| void GMainWindow::Connect3DStateEvents() { | ||||
|     connect(option_3d_button, &QPushButton::clicked, this, &GMainWindow::Toggle3D); | ||||
|     connect(factor_3d_slider, qOverload<int>(&QSlider::valueChanged), this, | ||||
|             [](int value) { Settings::values.factor_3d = value; }); | ||||
| } | ||||
|  | ||||
| void GMainWindow::OnDisplayTitleBars(bool show) { | ||||
|     QList<QDockWidget*> widgets = findChildren<QDockWidget*>(); | ||||
|  | ||||
| @@ -1219,7 +1271,6 @@ void GMainWindow::ShutdownGame() { | ||||
|  | ||||
|     // Disable status bar updates | ||||
|     status_bar_update_timer.stop(); | ||||
|     message_label->setVisible(false); | ||||
|     message_label_used_for_movie = false; | ||||
|     emu_speed_label->setVisible(false); | ||||
|     game_fps_label->setVisible(false); | ||||
| @@ -1900,6 +1951,7 @@ void GMainWindow::OnConfigure() { | ||||
|             setMouseTracking(false); | ||||
|         } | ||||
|         UpdateSecondaryWindowVisibility(); | ||||
|         Update3DState(); | ||||
|     } else { | ||||
|         Settings::values.input_profiles = old_input_profiles; | ||||
|         Settings::values.touch_from_button_maps = old_touch_from_button_maps; | ||||
| @@ -2160,22 +2212,18 @@ void GMainWindow::UpdateStatusBar() { | ||||
|     const auto play_mode = Core::Movie::GetInstance().GetPlayMode(); | ||||
|     if (play_mode == Core::Movie::PlayMode::Recording) { | ||||
|         message_label->setText(tr("Recording %1").arg(current)); | ||||
|         message_label->setVisible(true); | ||||
|         message_label_used_for_movie = true; | ||||
|         ui->action_Save_Movie->setEnabled(true); | ||||
|     } else if (play_mode == Core::Movie::PlayMode::Playing) { | ||||
|         message_label->setText(tr("Playing %1 / %2").arg(current, total)); | ||||
|         message_label->setVisible(true); | ||||
|         message_label_used_for_movie = true; | ||||
|         ui->action_Save_Movie->setEnabled(false); | ||||
|     } else if (play_mode == Core::Movie::PlayMode::MovieFinished) { | ||||
|         message_label->setText(tr("Movie Finished")); | ||||
|         message_label->setVisible(true); | ||||
|         message_label_used_for_movie = true; | ||||
|         ui->action_Save_Movie->setEnabled(false); | ||||
|     } else if (message_label_used_for_movie) { // Clear the label if movie was just closed | ||||
|         message_label->setText(QString{}); | ||||
|         message_label->setVisible(false); | ||||
|         message_label_used_for_movie = false; | ||||
|         ui->action_Save_Movie->setEnabled(false); | ||||
|     } | ||||
| @@ -2197,6 +2245,18 @@ void GMainWindow::UpdateStatusBar() { | ||||
|     emu_frametime_label->setVisible(true); | ||||
| } | ||||
|  | ||||
| void GMainWindow::Update3DState() { | ||||
|     static const std::array options_3d = {tr("Off"), tr("Side by Side"), tr("Anaglyph"), | ||||
|                                           tr("Interlaced"), tr("Reverse Interlaced")}; | ||||
|  | ||||
|     option_3d_button->setText( | ||||
|         tr("3D: %1").arg(options_3d[static_cast<int>(Settings::values.render_3d.GetValue())])); | ||||
|  | ||||
|     factor_3d_slider->setValue(Settings::values.factor_3d.GetValue()); | ||||
|     factor_3d_slider->setVisible(Settings::values.render_3d.GetValue() != | ||||
|                                  Settings::StereoRenderOption::Off); | ||||
| } | ||||
|  | ||||
| void GMainWindow::HideMouseCursor() { | ||||
|     if (emu_thread == nullptr || !UISettings::values.hide_mouse.GetValue()) { | ||||
|         mouse_hide_timer.stop(); | ||||
| @@ -2299,7 +2359,6 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det | ||||
|     if (emu_thread) { | ||||
|         emu_thread->SetRunning(true); | ||||
|         message_label->setText(status_message); | ||||
|         message_label->setVisible(true); | ||||
|         message_label_used_for_movie = false; | ||||
|     } | ||||
| } | ||||
| @@ -2309,6 +2368,12 @@ void GMainWindow::OnMenuAboutCitra() { | ||||
|     about.exec(); | ||||
| } | ||||
|  | ||||
| void GMainWindow::Toggle3D() { | ||||
|     Settings::values.render_3d = static_cast<Settings::StereoRenderOption>( | ||||
|         (static_cast<int>(Settings::values.render_3d.GetValue()) + 1) % num_options_3d); | ||||
|     Update3DState(); | ||||
| } | ||||
|  | ||||
| bool GMainWindow::ConfirmClose() { | ||||
|     if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) | ||||
|         return true; | ||||
| @@ -2418,8 +2483,18 @@ void GMainWindow::UpdateUITheme() { | ||||
|     QStringList theme_paths(default_theme_paths); | ||||
|  | ||||
|     if (is_default_theme || current_theme.isEmpty()) { | ||||
|         const QString theme_uri(QStringLiteral(":default/style.qss")); | ||||
|         QFile f(theme_uri); | ||||
|         if (f.open(QFile::ReadOnly | QFile::Text)) { | ||||
|             QTextStream ts(&f); | ||||
|             qApp->setStyleSheet(ts.readAll()); | ||||
|             setStyleSheet(ts.readAll()); | ||||
|         } else { | ||||
|             LOG_ERROR(Frontend, | ||||
|                       "Unable to open default stylesheet, falling back to empty stylesheet"); | ||||
|             qApp->setStyleSheet({}); | ||||
|             setStyleSheet({}); | ||||
|         } | ||||
|         theme_paths.append(default_icons); | ||||
|         QIcon::setThemeName(default_icons); | ||||
|     } else { | ||||
|   | ||||
| @@ -40,6 +40,8 @@ template <typename> | ||||
| class QFutureWatcher; | ||||
| class QLabel; | ||||
| class QProgressBar; | ||||
| class QPushButton; | ||||
| class QSlider; | ||||
| class RegistersWidget; | ||||
| class Updater; | ||||
| class WaitTreeWidget; | ||||
| @@ -118,6 +120,7 @@ private: | ||||
|     void RestoreUIState(); | ||||
|  | ||||
|     void ConnectWidgetEvents(); | ||||
|     void Connect3DStateEvents(); | ||||
|     void ConnectMenuEvents(); | ||||
|     void UpdateMenuState(); | ||||
|  | ||||
| @@ -225,6 +228,7 @@ private slots: | ||||
|     void OnStopVideoDumping(); | ||||
| #endif | ||||
|     void OnCoreError(Core::System::ResultStatus, std::string); | ||||
|     void Toggle3D(); | ||||
|     /// Called whenever a user selects Help->About Citra | ||||
|     void OnMenuAboutCitra(); | ||||
|     void OnUpdateFound(bool found, bool error); | ||||
| @@ -236,6 +240,7 @@ private slots: | ||||
| private: | ||||
|     Q_INVOKABLE void OnMoviePlaybackCompleted(); | ||||
|     void UpdateStatusBar(); | ||||
|     void Update3DState(); | ||||
|     void LoadTranslation(); | ||||
|     void UpdateWindowTitle(); | ||||
|     void UpdateUISettings(); | ||||
| @@ -259,6 +264,8 @@ private: | ||||
|     QLabel* emu_speed_label = nullptr; | ||||
|     QLabel* game_fps_label = nullptr; | ||||
|     QLabel* emu_frametime_label = nullptr; | ||||
|     QPushButton* option_3d_button = nullptr; | ||||
|     QSlider* factor_3d_slider = nullptr; | ||||
|     QTimer status_bar_update_timer; | ||||
|     bool message_label_used_for_movie = false; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user