mirror of
https://github.com/PabloMK7/citra.git
synced 2025-09-10 21:00:06 +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