yuzu, 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
							
								
									f761e3ef86
								
							
						
					
					
						commit
						a2be49305d
					
				@ -6,6 +6,7 @@
 | 
			
		||||
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "core/frontend/framebuffer_layout.h"
 | 
			
		||||
#include "core/settings.h"
 | 
			
		||||
 | 
			
		||||
namespace Layout {
 | 
			
		||||
 | 
			
		||||
@ -42,4 +43,18 @@ FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height) {
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FramebufferLayout FrameLayoutFromResolutionScale(u16 res_scale) {
 | 
			
		||||
    int width, height;
 | 
			
		||||
 | 
			
		||||
    if (Settings::values.use_docked_mode) {
 | 
			
		||||
        width = ScreenDocked::WidthDocked * res_scale;
 | 
			
		||||
        height = ScreenDocked::HeightDocked * res_scale;
 | 
			
		||||
    } else {
 | 
			
		||||
        width = ScreenUndocked::Width * res_scale;
 | 
			
		||||
        height = ScreenUndocked::Height * res_scale;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return DefaultFrameLayout(width, height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Layout
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@
 | 
			
		||||
namespace Layout {
 | 
			
		||||
 | 
			
		||||
enum ScreenUndocked : unsigned { Width = 1280, Height = 720 };
 | 
			
		||||
enum ScreenDocked : unsigned { WidthDocked = 1920, HeightDocked = 1080 };
 | 
			
		||||
 | 
			
		||||
/// Describes the layout of the window framebuffer
 | 
			
		||||
struct FramebufferLayout {
 | 
			
		||||
@ -34,4 +35,10 @@ struct FramebufferLayout {
 | 
			
		||||
 */
 | 
			
		||||
FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Convenience method to get frame layout by resolution scale
 | 
			
		||||
 * @param res_scale resolution scale factor
 | 
			
		||||
 */
 | 
			
		||||
FramebufferLayout FrameLayoutFromResolutionScale(u16 res_scale);
 | 
			
		||||
 | 
			
		||||
} // namespace Layout
 | 
			
		||||
 | 
			
		||||
@ -27,4 +27,16 @@ void RendererBase::UpdateCurrentFramebufferLayout() {
 | 
			
		||||
    render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RendererBase::RequestScreenshot(void* data, std::function<void()> callback,
 | 
			
		||||
                                     const Layout::FramebufferLayout& layout) {
 | 
			
		||||
    if (renderer_settings.screenshot_requested) {
 | 
			
		||||
        LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    renderer_settings.screenshot_bits = data;
 | 
			
		||||
    renderer_settings.screenshot_complete_callback = std::move(callback);
 | 
			
		||||
    renderer_settings.screenshot_framebuffer_layout = layout;
 | 
			
		||||
    renderer_settings.screenshot_requested = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace VideoCore
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@
 | 
			
		||||
#include <optional>
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/frontend/emu_window.h"
 | 
			
		||||
#include "video_core/gpu.h"
 | 
			
		||||
#include "video_core/rasterizer_interface.h"
 | 
			
		||||
 | 
			
		||||
@ -21,6 +22,12 @@ namespace VideoCore {
 | 
			
		||||
struct RendererSettings {
 | 
			
		||||
    std::atomic_bool use_framelimiter{false};
 | 
			
		||||
    std::atomic_bool set_background_color{false};
 | 
			
		||||
 | 
			
		||||
    // Screenshot
 | 
			
		||||
    std::atomic<bool> screenshot_requested{false};
 | 
			
		||||
    void* screenshot_bits;
 | 
			
		||||
    std::function<void()> screenshot_complete_callback;
 | 
			
		||||
    Layout::FramebufferLayout screenshot_framebuffer_layout;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class RendererBase : NonCopyable {
 | 
			
		||||
@ -57,9 +64,29 @@ public:
 | 
			
		||||
        return *rasterizer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Core::Frontend::EmuWindow& GetRenderWindow() {
 | 
			
		||||
        return render_window;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Core::Frontend::EmuWindow& GetRenderWindow() const {
 | 
			
		||||
        return render_window;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RendererSettings& Settings() {
 | 
			
		||||
        return renderer_settings;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const RendererSettings& Settings() const {
 | 
			
		||||
        return renderer_settings;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Refreshes the settings common to all renderers
 | 
			
		||||
    void RefreshBaseSettings();
 | 
			
		||||
 | 
			
		||||
    /// Request a screenshot of the next frame
 | 
			
		||||
    void RequestScreenshot(void* data, std::function<void()> callback,
 | 
			
		||||
                           const Layout::FramebufferLayout& layout);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
 | 
			
		||||
    std::unique_ptr<RasterizerInterface> rasterizer;
 | 
			
		||||
 | 
			
		||||
@ -138,7 +138,12 @@ void RendererOpenGL::SwapBuffers(
 | 
			
		||||
 | 
			
		||||
        // Load the framebuffer from memory, draw it to the screen, and swap buffers
 | 
			
		||||
        LoadFBToScreenInfo(*framebuffer);
 | 
			
		||||
        DrawScreen();
 | 
			
		||||
 | 
			
		||||
        if (renderer_settings.screenshot_requested)
 | 
			
		||||
            CaptureScreenshot();
 | 
			
		||||
 | 
			
		||||
        DrawScreen(render_window.GetFramebufferLayout());
 | 
			
		||||
 | 
			
		||||
        render_window.SwapBuffers();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -383,14 +388,13 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
 | 
			
		||||
/**
 | 
			
		||||
 * Draws the emulated screens to the emulator window.
 | 
			
		||||
 */
 | 
			
		||||
void RendererOpenGL::DrawScreen() {
 | 
			
		||||
void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
 | 
			
		||||
    if (renderer_settings.set_background_color) {
 | 
			
		||||
        // Update background color before drawing
 | 
			
		||||
        glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue,
 | 
			
		||||
                     0.0f);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto& layout = render_window.GetFramebufferLayout();
 | 
			
		||||
    const auto& screen = layout.screen;
 | 
			
		||||
 | 
			
		||||
    glViewport(0, 0, layout.width, layout.height);
 | 
			
		||||
@ -414,6 +418,37 @@ void RendererOpenGL::DrawScreen() {
 | 
			
		||||
/// Updates the framerate
 | 
			
		||||
void RendererOpenGL::UpdateFramerate() {}
 | 
			
		||||
 | 
			
		||||
void RendererOpenGL::CaptureScreenshot() {
 | 
			
		||||
    // Draw the current frame to the screenshot framebuffer
 | 
			
		||||
    screenshot_framebuffer.Create();
 | 
			
		||||
    GLuint old_read_fb = state.draw.read_framebuffer;
 | 
			
		||||
    GLuint old_draw_fb = state.draw.draw_framebuffer;
 | 
			
		||||
    state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle;
 | 
			
		||||
    state.Apply();
 | 
			
		||||
 | 
			
		||||
    Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
 | 
			
		||||
 | 
			
		||||
    GLuint renderbuffer;
 | 
			
		||||
    glGenRenderbuffers(1, &renderbuffer);
 | 
			
		||||
    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
 | 
			
		||||
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, layout.width, layout.height);
 | 
			
		||||
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
 | 
			
		||||
 | 
			
		||||
    DrawScreen(layout);
 | 
			
		||||
 | 
			
		||||
    glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
 | 
			
		||||
                 renderer_settings.screenshot_bits);
 | 
			
		||||
 | 
			
		||||
    screenshot_framebuffer.Release();
 | 
			
		||||
    state.draw.read_framebuffer = old_read_fb;
 | 
			
		||||
    state.draw.draw_framebuffer = old_draw_fb;
 | 
			
		||||
    state.Apply();
 | 
			
		||||
    glDeleteRenderbuffers(1, &renderbuffer);
 | 
			
		||||
 | 
			
		||||
    renderer_settings.screenshot_complete_callback();
 | 
			
		||||
    renderer_settings.screenshot_requested = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char* GetSource(GLenum source) {
 | 
			
		||||
#define RET(s)                                                                                     \
 | 
			
		||||
    case GL_DEBUG_SOURCE_##s:                                                                      \
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,10 @@ namespace Core::Frontend {
 | 
			
		||||
class EmuWindow;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Layout {
 | 
			
		||||
class FramebufferLayout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
 | 
			
		||||
/// Structure used for storing information about the textures for the Switch screen
 | 
			
		||||
@ -66,10 +70,12 @@ private:
 | 
			
		||||
 | 
			
		||||
    void ConfigureFramebufferTexture(TextureInfo& texture,
 | 
			
		||||
                                     const Tegra::FramebufferConfig& framebuffer);
 | 
			
		||||
    void DrawScreen();
 | 
			
		||||
    void DrawScreen(const Layout::FramebufferLayout& layout);
 | 
			
		||||
    void DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, float h);
 | 
			
		||||
    void UpdateFramerate();
 | 
			
		||||
 | 
			
		||||
    void CaptureScreenshot();
 | 
			
		||||
 | 
			
		||||
    // Loads framebuffer from emulated memory into the display information structure
 | 
			
		||||
    void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer);
 | 
			
		||||
    // Fills active OpenGL texture with the given RGBA color.
 | 
			
		||||
@ -82,6 +88,7 @@ private:
 | 
			
		||||
    OGLVertexArray vertex_array;
 | 
			
		||||
    OGLBuffer vertex_buffer;
 | 
			
		||||
    OGLProgram shader;
 | 
			
		||||
    OGLFramebuffer screenshot_framebuffer;
 | 
			
		||||
 | 
			
		||||
    /// Display information for Switch screen
 | 
			
		||||
    ScreenInfo screen_info;
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,8 @@
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/settings.h"
 | 
			
		||||
#include "video_core/renderer_base.h"
 | 
			
		||||
#include "video_core/renderer_opengl/renderer_opengl.h"
 | 
			
		||||
#include "video_core/video_core.h"
 | 
			
		||||
@ -13,4 +15,10 @@ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_wind
 | 
			
		||||
    return std::make_unique<OpenGL::RendererOpenGL>(emu_window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u16 GetResolutionScaleFactor(const RendererBase& renderer) {
 | 
			
		||||
    return !Settings::values.resolution_factor
 | 
			
		||||
               ? renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio()
 | 
			
		||||
               : Settings::values.resolution_factor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace VideoCore
 | 
			
		||||
 | 
			
		||||
@ -22,4 +22,6 @@ class RendererBase;
 | 
			
		||||
 */
 | 
			
		||||
std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window);
 | 
			
		||||
 | 
			
		||||
u16 GetResolutionScaleFactor(const RendererBase& renderer);
 | 
			
		||||
 | 
			
		||||
} // namespace VideoCore
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,8 @@
 | 
			
		||||
#include "input_common/keyboard.h"
 | 
			
		||||
#include "input_common/main.h"
 | 
			
		||||
#include "input_common/motion_emu.h"
 | 
			
		||||
#include "video_core/renderer_base.h"
 | 
			
		||||
#include "video_core/video_core.h"
 | 
			
		||||
#include "yuzu/bootmanager.h"
 | 
			
		||||
 | 
			
		||||
EmuThread::EmuThread(GRenderWindow* render_window) : render_window(render_window) {}
 | 
			
		||||
@ -333,6 +335,22 @@ void GRenderWindow::InitRenderTarget() {
 | 
			
		||||
    BackupGeometry();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GRenderWindow::CaptureScreenshot(u16 res_scale, const QString& screenshot_path) {
 | 
			
		||||
    auto& renderer = Core::System::GetInstance().Renderer();
 | 
			
		||||
 | 
			
		||||
    if (!res_scale)
 | 
			
		||||
        res_scale = VideoCore::GetResolutionScaleFactor(renderer);
 | 
			
		||||
 | 
			
		||||
    const Layout::FramebufferLayout layout{Layout::FrameLayoutFromResolutionScale(res_scale)};
 | 
			
		||||
    screenshot_image = QImage(QSize(layout.width, layout.height), QImage::Format_RGB32);
 | 
			
		||||
    renderer.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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -445,6 +445,8 @@ void Config::ReadValues() {
 | 
			
		||||
    UISettings::values.theme = qt_config->value("theme", UISettings::themes[0].second).toString();
 | 
			
		||||
    UISettings::values.enable_discord_presence =
 | 
			
		||||
        qt_config->value("enable_discord_presence", true).toBool();
 | 
			
		||||
    UISettings::values.screenshot_resolution_factor =
 | 
			
		||||
        static_cast<u16>(qt_config->value("screenshot_resolution_factor", 0).toUInt());
 | 
			
		||||
 | 
			
		||||
    qt_config->beginGroup("UIGameList");
 | 
			
		||||
    UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool();
 | 
			
		||||
@ -648,6 +650,8 @@ void Config::SaveValues() {
 | 
			
		||||
    qt_config->beginGroup("UI");
 | 
			
		||||
    qt_config->setValue("theme", UISettings::values.theme);
 | 
			
		||||
    qt_config->setValue("enable_discord_presence", UISettings::values.enable_discord_presence);
 | 
			
		||||
    qt_config->setValue("screenshot_resolution_factor",
 | 
			
		||||
                        UISettings::values.screenshot_resolution_factor);
 | 
			
		||||
 | 
			
		||||
    qt_config->beginGroup("UIGameList");
 | 
			
		||||
    qt_config->setValue("show_unknown", UISettings::values.show_unknown);
 | 
			
		||||
@ -669,6 +673,7 @@ void Config::SaveValues() {
 | 
			
		||||
    qt_config->beginGroup("Paths");
 | 
			
		||||
    qt_config->setValue("romsPath", UISettings::values.roms_path);
 | 
			
		||||
    qt_config->setValue("symbolsPath", UISettings::values.symbols_path);
 | 
			
		||||
    qt_config->setValue("screenshotPath", UISettings::values.screenshot_path);
 | 
			
		||||
    qt_config->setValue("gameListRootDir", UISettings::values.gamedir);
 | 
			
		||||
    qt_config->setValue("gameListDeepScan", UISettings::values.gamedir_deepscan);
 | 
			
		||||
    qt_config->setValue("recentFiles", UISettings::values.recent_files);
 | 
			
		||||
 | 
			
		||||
@ -334,6 +334,9 @@ void GMainWindow::InitializeHotkeys() {
 | 
			
		||||
                                   Qt::ApplicationShortcut);
 | 
			
		||||
    hotkey_registry.RegisterHotkey("Main Window", "Load Amiibo", QKeySequence(Qt::Key_F2),
 | 
			
		||||
                                   Qt::ApplicationShortcut);
 | 
			
		||||
    hotkey_registry.RegisterHotkey("Main Window", "Capture Screenshot",
 | 
			
		||||
                                   QKeySequence(QKeySequence::Print));
 | 
			
		||||
 | 
			
		||||
    hotkey_registry.LoadHotkeys();
 | 
			
		||||
 | 
			
		||||
    connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated,
 | 
			
		||||
@ -393,6 +396,12 @@ void GMainWindow::InitializeHotkeys() {
 | 
			
		||||
                    OnLoadAmiibo();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
    connect(hotkey_registry.GetHotkey("Main Window", "Capture Screenshot", this),
 | 
			
		||||
            &QShortcut::activated, this, [&] {
 | 
			
		||||
                if (emu_thread->IsRunning()) {
 | 
			
		||||
                    OnCaptureScreenshot();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::SetDefaultUIGeometry() {
 | 
			
		||||
@ -488,6 +497,10 @@ void GMainWindow::ConnectMenuEvents() {
 | 
			
		||||
        hotkey_registry.GetHotkey("Main Window", "Fullscreen", this)->key());
 | 
			
		||||
    connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
 | 
			
		||||
 | 
			
		||||
    // Movie
 | 
			
		||||
    connect(ui.action_Capture_Screenshot, &QAction::triggered, this,
 | 
			
		||||
            &GMainWindow::OnCaptureScreenshot);
 | 
			
		||||
 | 
			
		||||
    // Help
 | 
			
		||||
    connect(ui.action_Open_yuzu_Folder, &QAction::triggered, this, &GMainWindow::OnOpenYuzuFolder);
 | 
			
		||||
    connect(ui.action_Rederive, &QAction::triggered, this,
 | 
			
		||||
@ -724,6 +737,7 @@ void GMainWindow::ShutdownGame() {
 | 
			
		||||
    ui.action_Restart->setEnabled(false);
 | 
			
		||||
    ui.action_Report_Compatibility->setEnabled(false);
 | 
			
		||||
    ui.action_Load_Amiibo->setEnabled(false);
 | 
			
		||||
    ui.action_Capture_Screenshot->setEnabled(false);
 | 
			
		||||
    render_window->hide();
 | 
			
		||||
    game_list->show();
 | 
			
		||||
    game_list->setFilterFocus();
 | 
			
		||||
@ -1261,6 +1275,7 @@ void GMainWindow::OnStartGame() {
 | 
			
		||||
 | 
			
		||||
    discord_rpc->Update();
 | 
			
		||||
    ui.action_Load_Amiibo->setEnabled(true);
 | 
			
		||||
    ui.action_Capture_Screenshot->setEnabled(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnPauseGame() {
 | 
			
		||||
@ -1269,6 +1284,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() {
 | 
			
		||||
@ -1431,6 +1447,18 @@ void GMainWindow::OnToggleFilterBar() {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
 | 
			
		||||
@ -186,6 +186,7 @@ private slots:
 | 
			
		||||
    void ShowFullscreen();
 | 
			
		||||
    void HideFullscreen();
 | 
			
		||||
    void ToggleWindowMode();
 | 
			
		||||
    void OnCaptureScreenshot();
 | 
			
		||||
    void OnCoreError(Core::System::ResultStatus, std::string);
 | 
			
		||||
    void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -101,11 +101,13 @@
 | 
			
		||||
    <addaction name="action_Show_Status_Bar"/>
 | 
			
		||||
    <addaction name="menu_View_Debugging"/>
 | 
			
		||||
   </widget>
 | 
			
		||||
   <widget class ="QMenu" name="menu_Tools">
 | 
			
		||||
   <widget class="QMenu" name="menu_Tools">
 | 
			
		||||
    <property name="title">
 | 
			
		||||
     <string>Tools</string>
 | 
			
		||||
    </property>
 | 
			
		||||
    <addaction name="action_Rederive" />
 | 
			
		||||
    <addaction name="action_Rederive"/>
 | 
			
		||||
    <addaction name="separator"/>
 | 
			
		||||
    <addaction name="action_Capture_Screenshot"/>
 | 
			
		||||
   </widget>
 | 
			
		||||
   <widget class="QMenu" name="menu_Help">
 | 
			
		||||
    <property name="title">
 | 
			
		||||
@ -118,7 +120,7 @@
 | 
			
		||||
   <addaction name="menu_File"/>
 | 
			
		||||
   <addaction name="menu_Emulation"/>
 | 
			
		||||
   <addaction name="menu_View"/>
 | 
			
		||||
   <addaction name="menu_Tools" />
 | 
			
		||||
   <addaction name="menu_Tools"/>
 | 
			
		||||
   <addaction name="menu_Help"/>
 | 
			
		||||
  </widget>
 | 
			
		||||
  <action name="action_Install_File_NAND">
 | 
			
		||||
@ -173,11 +175,11 @@
 | 
			
		||||
    <string>&Stop</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
   <action name="action_Rederive">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
       <string>Reinitialize keys...</string>
 | 
			
		||||
     </property>
 | 
			
		||||
   </action>
 | 
			
		||||
  <action name="action_Rederive">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Reinitialize keys...</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="action_About">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>About yuzu</string>
 | 
			
		||||
@ -252,39 +254,47 @@
 | 
			
		||||
    <string>Fullscreen</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
   <action name="action_Restart">
 | 
			
		||||
     <property name="enabled">
 | 
			
		||||
       <bool>false</bool>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="text">
 | 
			
		||||
       <string>Restart</string>
 | 
			
		||||
     </property>
 | 
			
		||||
   </action>
 | 
			
		||||
  <action name="action_Load_Amiibo">
 | 
			
		||||
    <property name="enabled">
 | 
			
		||||
      <bool>false</bool>
 | 
			
		||||
    </property>
 | 
			
		||||
    <property name="text">
 | 
			
		||||
      <string>Load Amiibo...</string>
 | 
			
		||||
    </property>
 | 
			
		||||
  <action name="action_Restart">
 | 
			
		||||
   <property name="enabled">
 | 
			
		||||
    <bool>false</bool>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Restart</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
   <action name="action_Report_Compatibility">
 | 
			
		||||
     <property name="enabled">
 | 
			
		||||
       <bool>false</bool>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="text">
 | 
			
		||||
       <string>Report Compatibility</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="visible">
 | 
			
		||||
       <bool>false</bool>
 | 
			
		||||
     </property>
 | 
			
		||||
   </action>
 | 
			
		||||
   <action name="action_Open_yuzu_Folder">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
       <string>Open yuzu Folder</string>
 | 
			
		||||
     </property>
 | 
			
		||||
   </action>
 | 
			
		||||
  </widget>
 | 
			
		||||
  <action name="action_Load_Amiibo">
 | 
			
		||||
   <property name="enabled">
 | 
			
		||||
    <bool>false</bool>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Load Amiibo...</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="action_Report_Compatibility">
 | 
			
		||||
   <property name="enabled">
 | 
			
		||||
    <bool>false</bool>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Report Compatibility</string>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="visible">
 | 
			
		||||
    <bool>false</bool>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="action_Open_yuzu_Folder">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Open yuzu Folder</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="action_Capture_Screenshot">
 | 
			
		||||
   <property name="enabled">
 | 
			
		||||
    <bool>false</bool>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Capture Screenshot</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <resources/>
 | 
			
		||||
 <connections/>
 | 
			
		||||
</ui>
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,7 @@
 | 
			
		||||
#include <QByteArray>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
namespace UISettings {
 | 
			
		||||
 | 
			
		||||
@ -42,8 +43,11 @@ struct Values {
 | 
			
		||||
    // Discord RPC
 | 
			
		||||
    bool enable_discord_presence;
 | 
			
		||||
 | 
			
		||||
    u16 screenshot_resolution_factor;
 | 
			
		||||
 | 
			
		||||
    QString roms_path;
 | 
			
		||||
    QString symbols_path;
 | 
			
		||||
    QString screenshot_path;
 | 
			
		||||
    QString gamedir;
 | 
			
		||||
    bool gamedir_deepscan;
 | 
			
		||||
    QStringList recent_files;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user