mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	citra_qt, video_core: Screenshot functionality
Allows capturing screenshot at the current internal resolution (native for software renderer), but a setting is available to capture it in other resolutions. The screenshot is saved to a single PNG in the current layout.
This commit is contained in:
		
							parent
							
								
									7e90abec78
								
							
						
					
					
						commit
						071b41cb61
					
				
					 14 changed files with 202 additions and 14 deletions
				
			
		|  | @ -15,6 +15,7 @@ | |||
| #include "input_common/main.h" | ||||
| #include "input_common/motion_emu.h" | ||||
| #include "network/network.h" | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
| EmuThread::EmuThread(GRenderWindow* render_window) : render_window(render_window) {} | ||||
| 
 | ||||
|  | @ -335,6 +336,19 @@ void GRenderWindow::InitRenderTarget() { | |||
|     BackupGeometry(); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::CaptureScreenshot(u16 res_scale, const QString& screenshot_path) { | ||||
|     if (!res_scale) | ||||
|         res_scale = VideoCore::GetResolutionScaleFactor(); | ||||
|     const Layout::FramebufferLayout layout{Layout::FrameLayoutFromResolutionScale(res_scale)}; | ||||
|     screenshot_image = QImage(QSize(layout.width, layout.height), QImage::Format_RGB32); | ||||
|     VideoCore::RequestScreenshot(screenshot_image.bits(), | ||||
|                                  [=] { | ||||
|                                      screenshot_image.mirrored(false, true).save(screenshot_path); | ||||
|                                      LOG_INFO(Frontend, "The screenshot is saved."); | ||||
|                                  }, | ||||
|                                  layout); | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::OnMinimalClientAreaChangeRequest( | ||||
|     const std::pair<unsigned, unsigned>& minimal_size) { | ||||
|     setMinimumSize(minimal_size.first, minimal_size.second); | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include <condition_variable> | ||||
| #include <mutex> | ||||
| #include <QGLWidget> | ||||
| #include <QImage> | ||||
| #include <QThread> | ||||
| #include "common/thread.h" | ||||
| #include "core/core.h" | ||||
|  | @ -139,6 +140,8 @@ public: | |||
| 
 | ||||
|     void InitRenderTarget(); | ||||
| 
 | ||||
|     void CaptureScreenshot(u16 res_scale, const QString& screenshot_path); | ||||
| 
 | ||||
| public slots: | ||||
|     void moveContext(); // overridden
 | ||||
| 
 | ||||
|  | @ -165,6 +168,9 @@ private: | |||
| 
 | ||||
|     EmuThread* emu_thread; | ||||
| 
 | ||||
|     /// Temporary storage of the screenshot taken
 | ||||
|     QImage screenshot_image; | ||||
| 
 | ||||
| protected: | ||||
|     void showEvent(QShowEvent* event) override; | ||||
| }; | ||||
|  |  | |||
|  | @ -206,6 +206,8 @@ void Config::ReadValues() { | |||
|     UISettings::values.theme = ReadSetting("theme", UISettings::themes[0].second).toString(); | ||||
|     UISettings::values.enable_discord_presence = | ||||
|         ReadSetting("enable_discord_presence", true).toBool(); | ||||
|     UISettings::values.screenshot_resolution_factor = | ||||
|         static_cast<u16>(ReadSetting("screenshot_resolution_factor", 0).toUInt()); | ||||
| 
 | ||||
|     qt_config->beginGroup("Updater"); | ||||
|     UISettings::values.check_for_update_on_start = | ||||
|  | @ -251,6 +253,7 @@ void Config::ReadValues() { | |||
|     UISettings::values.symbols_path = ReadSetting("symbolsPath").toString(); | ||||
|     UISettings::values.movie_record_path = ReadSetting("movieRecordPath").toString(); | ||||
|     UISettings::values.movie_playback_path = ReadSetting("moviePlaybackPath").toString(); | ||||
|     UISettings::values.screenshot_path = ReadSetting("screenshotPath").toString(); | ||||
|     UISettings::values.game_dir_deprecated = ReadSetting("gameListRootDir", ".").toString(); | ||||
|     UISettings::values.game_dir_deprecated_deepscan = | ||||
|         ReadSetting("gameListDeepScan", false).toBool(); | ||||
|  | @ -460,6 +463,8 @@ void Config::SaveValues() { | |||
|     qt_config->beginGroup("UI"); | ||||
|     WriteSetting("theme", UISettings::values.theme, UISettings::themes[0].second); | ||||
|     WriteSetting("enable_discord_presence", UISettings::values.enable_discord_presence, true); | ||||
|     WriteSetting("screenshot_resolution_factor", UISettings::values.screenshot_resolution_factor, | ||||
|                  0); | ||||
| 
 | ||||
|     qt_config->beginGroup("Updater"); | ||||
|     WriteSetting("check_for_update_on_start", UISettings::values.check_for_update_on_start, true); | ||||
|  | @ -487,6 +492,7 @@ void Config::SaveValues() { | |||
|     WriteSetting("symbolsPath", UISettings::values.symbols_path); | ||||
|     WriteSetting("movieRecordPath", UISettings::values.movie_record_path); | ||||
|     WriteSetting("moviePlaybackPath", UISettings::values.movie_playback_path); | ||||
|     WriteSetting("screenshotPath", UISettings::values.screenshot_path); | ||||
|     qt_config->beginWriteArray("gamedirs"); | ||||
|     for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) { | ||||
|         qt_config->setArrayIndex(i); | ||||
|  |  | |||
|  | @ -365,6 +365,7 @@ void GMainWindow::InitializeHotkeys() { | |||
|                                    Qt::ApplicationShortcut); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Remove Amiibo", QKeySequence(Qt::Key_F3), | ||||
|                                    Qt::ApplicationShortcut); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Capture Screenshot", QKeySequence(tr("CTRL+P"))); | ||||
| 
 | ||||
|     hotkey_registry.LoadHotkeys(); | ||||
| 
 | ||||
|  | @ -439,6 +440,12 @@ void GMainWindow::InitializeHotkeys() { | |||
|                     OnRemoveAmiibo(); | ||||
|                 } | ||||
|             }); | ||||
|     connect(hotkey_registry.GetHotkey("Main Window", "Capture Screenshot", this), | ||||
|             &QShortcut::activated, this, [&] { | ||||
|                 if (emu_thread->IsRunning()) { | ||||
|                     OnCaptureScreenshot(); | ||||
|                 } | ||||
|             }); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::ShowUpdaterWidgets() { | ||||
|  | @ -588,6 +595,8 @@ void GMainWindow::ConnectMenuEvents() { | |||
|             Core::System::GetInstance().frame_limiter.AdvanceFrame(); | ||||
|         } | ||||
|     }); | ||||
|     connect(ui.action_Capture_Screenshot, &QAction::triggered, this, | ||||
|             &GMainWindow::OnCaptureScreenshot); | ||||
| 
 | ||||
|     // Help
 | ||||
|     connect(ui.action_Open_Citra_Folder, &QAction::triggered, this, | ||||
|  | @ -882,6 +891,7 @@ void GMainWindow::ShutdownGame() { | |||
|     ui.action_Enable_Frame_Advancing->setEnabled(false); | ||||
|     ui.action_Enable_Frame_Advancing->setChecked(false); | ||||
|     ui.action_Advance_Frame->setEnabled(false); | ||||
|     ui.action_Capture_Screenshot->setEnabled(false); | ||||
|     render_window->hide(); | ||||
|     if (game_list->isEmpty()) | ||||
|         game_list_placeholder->show(); | ||||
|  | @ -1169,6 +1179,7 @@ void GMainWindow::OnStartGame() { | |||
|     ui.action_Load_Amiibo->setEnabled(true); | ||||
|     ui.action_Report_Compatibility->setEnabled(true); | ||||
|     ui.action_Enable_Frame_Advancing->setEnabled(true); | ||||
|     ui.action_Capture_Screenshot->setEnabled(true); | ||||
| 
 | ||||
|     discord_rpc->Update(); | ||||
| } | ||||
|  | @ -1179,6 +1190,7 @@ void GMainWindow::OnPauseGame() { | |||
|     ui.action_Start->setEnabled(true); | ||||
|     ui.action_Pause->setEnabled(false); | ||||
|     ui.action_Stop->setEnabled(true); | ||||
|     ui.action_Capture_Screenshot->setEnabled(false); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnStopGame() { | ||||
|  | @ -1539,6 +1551,18 @@ void GMainWindow::OnStopRecordingPlayback() { | |||
|     ui.action_Stop_Recording_Playback->setEnabled(false); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnCaptureScreenshot() { | ||||
|     OnPauseGame(); | ||||
|     const QString path = | ||||
|         QFileDialog::getSaveFileName(this, tr("Capture Screenshot"), | ||||
|                                      UISettings::values.screenshot_path, tr("PNG Image (*.png)")); | ||||
|     if (!path.isEmpty()) { | ||||
|         UISettings::values.screenshot_path = QFileInfo(path).path(); | ||||
|         render_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor, path); | ||||
|     } | ||||
|     OnStartGame(); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::UpdateStatusBar() { | ||||
|     if (emu_thread == nullptr) { | ||||
|         status_bar_update_timer.stop(); | ||||
|  |  | |||
|  | @ -183,6 +183,7 @@ private slots: | |||
|     void OnRecordMovie(); | ||||
|     void OnPlayMovie(); | ||||
|     void OnStopRecordingPlayback(); | ||||
|     void OnCaptureScreenshot(); | ||||
|     void OnCoreError(Core::System::ResultStatus, std::string); | ||||
|     /// Called whenever a user selects Help->About Citra
 | ||||
|     void OnMenuAboutCitra(); | ||||
|  |  | |||
|  | @ -131,6 +131,8 @@ | |||
|     <addaction name="separator"/> | ||||
|     <addaction name="action_Enable_Frame_Advancing"/> | ||||
|     <addaction name="action_Advance_Frame"/> | ||||
|     <addaction name="separator"/> | ||||
|     <addaction name="action_Capture_Screenshot"/> | ||||
|    </widget> | ||||
|    <widget class="QMenu" name="menu_Multiplayer"> | ||||
|     <property name="enabled"> | ||||
|  | @ -315,6 +317,14 @@ | |||
|     <string>Advance Frame</string> | ||||
|    </property> | ||||
|   </action> | ||||
|   <action name="action_Capture_Screenshot"> | ||||
|    <property name="enabled"> | ||||
|     <bool>false</bool> | ||||
|    </property> | ||||
|    <property name="text"> | ||||
|     <string>Capture Screenshot</string> | ||||
|    </property> | ||||
|   </action> | ||||
|   <action name="action_View_Lobby"> | ||||
|    <property name="enabled"> | ||||
|     <bool>true</bool> | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include <QMetaType> | ||||
| #include <QString> | ||||
| #include <QStringList> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace UISettings { | ||||
| 
 | ||||
|  | @ -78,10 +79,13 @@ struct Values { | |||
|     GameListText game_list_row_2; | ||||
|     bool game_list_hide_no_icon; | ||||
| 
 | ||||
|     u16 screenshot_resolution_factor; | ||||
| 
 | ||||
|     QString roms_path; | ||||
|     QString symbols_path; | ||||
|     QString movie_record_path; | ||||
|     QString movie_playback_path; | ||||
|     QString screenshot_path; | ||||
|     QString game_dir_deprecated; | ||||
|     bool game_dir_deprecated_deepscan; | ||||
|     QList<UISettings::GameDir> game_dirs; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue