Screenshot functionality Added
Added a screenshot functionality based on this pr https://github.com/xenia-project/xenia/pull/2074 and added some minor adjustments. GUI wise, "take screenshot" is under the Display menu and the keyboard shortcut to take it is F10 The screenshots folder will save to where xenia.exe or xenia_canary.exe is located. As for save paths, it will only use the id of the game due to illegal characters in some titles.
This commit is contained in:
parent
34322ebb41
commit
e4408b6bc3
|
@ -17,8 +17,10 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "third_party/cpptoml/include/cpptoml.h"
|
#include "third_party/cpptoml/include/cpptoml.h"
|
||||||
|
#include "third_party/fmt/include/fmt/chrono.h"
|
||||||
#include "third_party/fmt/include/fmt/format.h"
|
#include "third_party/fmt/include/fmt/format.h"
|
||||||
#include "third_party/imgui/imgui.h"
|
#include "third_party/imgui/imgui.h"
|
||||||
|
#include "third_party/stb/stb_image_write.h"
|
||||||
#include "xenia/base/assert.h"
|
#include "xenia/base/assert.h"
|
||||||
#include "xenia/base/clock.h"
|
#include "xenia/base/clock.h"
|
||||||
#include "xenia/base/cvar.h"
|
#include "xenia/base/cvar.h"
|
||||||
|
@ -649,6 +651,9 @@ bool EmulatorWindow::Initialize() {
|
||||||
display_menu->AddChild(
|
display_menu->AddChild(
|
||||||
MenuItem::Create(MenuItem::Type::kString, "&Fullscreen", "F11",
|
MenuItem::Create(MenuItem::Type::kString, "&Fullscreen", "F11",
|
||||||
std::bind(&EmulatorWindow::ToggleFullscreen, this)));
|
std::bind(&EmulatorWindow::ToggleFullscreen, this)));
|
||||||
|
display_menu->AddChild(
|
||||||
|
MenuItem::Create(MenuItem::Type::kString, "&Take Screenshot", "F10",
|
||||||
|
std::bind(&EmulatorWindow::TakeScreenshot, this)));
|
||||||
}
|
}
|
||||||
main_menu->AddChild(std::move(display_menu));
|
main_menu->AddChild(std::move(display_menu));
|
||||||
|
|
||||||
|
@ -833,6 +838,10 @@ void EmulatorWindow::OnKeyDown(ui::KeyEvent& e) {
|
||||||
case ui::VirtualKey::kF11: {
|
case ui::VirtualKey::kF11: {
|
||||||
ToggleFullscreen();
|
ToggleFullscreen();
|
||||||
} break;
|
} break;
|
||||||
|
case ui::VirtualKey::kF10: {
|
||||||
|
TakeScreenshot();
|
||||||
|
} break;
|
||||||
|
|
||||||
case ui::VirtualKey::kEscape: {
|
case ui::VirtualKey::kEscape: {
|
||||||
// Allow users to escape fullscreen (but not enter it).
|
// Allow users to escape fullscreen (but not enter it).
|
||||||
if (!window_->IsFullscreen()) {
|
if (!window_->IsFullscreen()) {
|
||||||
|
@ -890,6 +899,71 @@ void EmulatorWindow::OnMouseUp(const ui::MouseEvent& e) {
|
||||||
last_mouse_up = steady_clock::now();
|
last_mouse_up = steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmulatorWindow::TakeScreenshot() {
|
||||||
|
xe::ui::RawImage image;
|
||||||
|
if (!GetGraphicsSystemPresenter()->CaptureGuestOutput(image) ||
|
||||||
|
GetGraphicsSystemPresenter() == nullptr) {
|
||||||
|
XELOGE("Failed to capture guest output for screenshot");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ExportScreenshot(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatorWindow::ExportScreenshot(const xe::ui::RawImage& image) {
|
||||||
|
auto t = std::time(nullptr);
|
||||||
|
|
||||||
|
// The format is: Year-Month-DayTHours-Minutes-Seconds based off ISO 8601
|
||||||
|
std::string datetime = fmt::format("{:%Y-%m-%dT%H-%M-%S}", fmt::localtime(t));
|
||||||
|
|
||||||
|
// Get the title id of the game because some titles contain characters that
|
||||||
|
// cannot be used as a directory
|
||||||
|
std::string title_id;
|
||||||
|
if (emulator()->title_id()) {
|
||||||
|
title_id = fmt::format("{:08X}", emulator()->title_id());
|
||||||
|
} else {
|
||||||
|
XELOGE("Failed to get the current title id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find where xenia.exe or xenia_canary.exe is located and create a
|
||||||
|
// screenshots folder
|
||||||
|
auto screenshot_path =
|
||||||
|
(xe::filesystem::GetExecutableFolder() / "screenshots" / title_id);
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(screenshot_path)) {
|
||||||
|
std::filesystem::create_directories(screenshot_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string filename = fmt::format("{} - {}.png", title_id, datetime);
|
||||||
|
SaveImage(screenshot_path / filename, image);
|
||||||
|
|
||||||
|
xe::ui::ImGuiDialog::ShowMessageBox(
|
||||||
|
imgui_drawer_.get(), "Screenshot saved",
|
||||||
|
fmt::format("Screenshot saved to {}", xe::path_to_utf8(screenshot_path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a RawImage into a PNG file
|
||||||
|
void EmulatorWindow::SaveImage(const std::filesystem::path& filepath,
|
||||||
|
const xe::ui::RawImage& image) {
|
||||||
|
auto file = std::ofstream(filepath, std::ios::binary);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
XELOGE("Failed to open file for writing: {}", xe::path_to_utf8(filepath));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = stbi_write_png_to_func(
|
||||||
|
[](void* context, void* data, int size) {
|
||||||
|
auto file = reinterpret_cast<std::ofstream*>(context);
|
||||||
|
file->write(reinterpret_cast<const char*>(data), size);
|
||||||
|
},
|
||||||
|
&file, image.width, image.height, 4, image.data.data(),
|
||||||
|
(int)image.stride);
|
||||||
|
if (result == 0) {
|
||||||
|
XELOGE("Failed to write PNG to file: {}", xe::path_to_utf8(filepath));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EmulatorWindow::ToggleFullscreenOnDoubleClick() {
|
void EmulatorWindow::ToggleFullscreenOnDoubleClick() {
|
||||||
// this function tests if user has double clicked.
|
// this function tests if user has double clicked.
|
||||||
// if double click was achieved the fullscreen gets toggled
|
// if double click was achieved the fullscreen gets toggled
|
||||||
|
|
|
@ -87,6 +87,11 @@ class EmulatorWindow {
|
||||||
void ToggleFullscreen();
|
void ToggleFullscreen();
|
||||||
void SetInitializingShaderStorage(bool initializing);
|
void SetInitializingShaderStorage(bool initializing);
|
||||||
|
|
||||||
|
void TakeScreenshot();
|
||||||
|
void ExportScreenshot(const xe::ui::RawImage& image);
|
||||||
|
void SaveImage(const std::filesystem::path& path,
|
||||||
|
const xe::ui::RawImage& image);
|
||||||
|
|
||||||
// Types of button functions for hotkeys.
|
// Types of button functions for hotkeys.
|
||||||
enum class ButtonFunctions {
|
enum class ButtonFunctions {
|
||||||
ToggleFullscreen,
|
ToggleFullscreen,
|
||||||
|
|
Loading…
Reference in New Issue