diff --git a/include/Cubed/render/renderer.hpp b/include/Cubed/render/renderer.hpp index b2deb3f..5016917 100644 --- a/include/Cubed/render/renderer.hpp +++ b/include/Cubed/render/renderer.hpp @@ -25,7 +25,7 @@ class DevPanel; class Renderer { public: constexpr static int NUM_VAO = 7; - + constexpr static const char* SCREENSHOT_PATH = "./screenshot"; Renderer(TextureManager& texture_manager, Config& config); ~Renderer(); void reload_config(); @@ -83,6 +83,8 @@ public: ModelRender& model_renderer(); + void save_screenshot(); + private: TextureManager& m_texture_manager; bool m_init = false; @@ -98,6 +100,8 @@ private: float m_window_width = 0.0f; float m_window_height = 0.0f; + bool m_save_screenshot = false; + glm::mat4 m_world_proj_matrix; std::unique_ptr m_sky_vbo; @@ -129,6 +133,7 @@ private: void updata_framebuffer(int width, int height); void init_quad(); void init_text(); + void handle_screenshot(); }; } // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/tools/time_tools.hpp b/include/Cubed/tools/time_tools.hpp index 3c22df6..36a6c12 100644 --- a/include/Cubed/tools/time_tools.hpp +++ b/include/Cubed/tools/time_tools.hpp @@ -1,11 +1,23 @@ #pragma once #include +#include #include +#include +#include namespace Cubed { namespace Tools { // return ms inline uint64_t get_time_ticks() { return SDL_GetTicks(); } + +inline std::string get_time_date_str() { + static auto* zone = std::chrono::current_zone(); + auto now = std::chrono::system_clock::now(); + auto local = + std::chrono::time_point_cast(zone->to_local(now)); + return std::format("{:%F %T}", local); +} + } // namespace Tools } // namespace Cubed \ No newline at end of file diff --git a/src/render/renderer.cpp b/src/render/renderer.cpp index b6d974c..d43b80d 100644 --- a/src/render/renderer.cpp +++ b/src/render/renderer.cpp @@ -9,10 +9,13 @@ #include "Cubed/tools/font.hpp" #include "Cubed/tools/log.hpp" #include "Cubed/tools/shader_tools.hpp" +#include "Cubed/tools/time_tools.hpp" +#include #include #include - +#include +namespace fs = std::filesystem; namespace Cubed { Renderer::Renderer(TextureManager& texture_manager, Config& config) @@ -139,7 +142,7 @@ void Renderer::begin_frame() { glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void Renderer::end_frame() {} +void Renderer::end_frame() { handle_screenshot(); } void Renderer::begin_render_ui() { glEnable(GL_BLEND); @@ -288,6 +291,34 @@ bool Renderer::handle_frame_buffer_resize_event( return false; } +void Renderer::handle_screenshot() { + if (!m_save_screenshot) { + return; + } + m_save_screenshot = false; + std::array screen_stats; + glGetIntegerv(GL_VIEWPORT, screen_stats.data()); + int width = screen_stats[2]; + int height = screen_stats[3]; + std::vector pixels(width * height * 4); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + std::vector flipped_pixels(width * height * 4); + for (int y = 0; y < height; ++y) { + std::memcpy(&flipped_pixels[y * width * 4], + &pixels[(height - 1 - y) * width * 4], width * 4); + } + fs::path path = SCREENSHOT_PATH; + fs::create_directories(path); + fs::path image = + path / std::format("screenshot {}.png", Tools::get_time_date_str()); + if (!stbi_write_png(image.c_str(), width, height, 4, flipped_pixels.data(), + width * 4)) { + Logger::error("Failed to write {} image", image.c_str()); + } else { + Logger::info("save {} success!", image.c_str()); + } +} + float& Renderer::ambient_strength() { return m_world_renderer.ambient_strength(); } @@ -341,4 +372,5 @@ float Renderer::frame_width() const { return m_frame_width; } const glm::mat4& Renderer::p_mat() const { return m_world_proj_matrix; } const std::vector& Renderer::vao() const { return m_vao; } ModelRender& Renderer::model_renderer() { return m_model_renderer; } +void Renderer::save_screenshot() { m_save_screenshot = true; } } // namespace Cubed \ No newline at end of file diff --git a/src/scene/world_scene.cpp b/src/scene/world_scene.cpp index 6e5b0e1..d4c6a05 100644 --- a/src/scene/world_scene.cpp +++ b/src/scene/world_scene.cpp @@ -3,6 +3,7 @@ #include "Cubed/app.hpp" #include "Cubed/render/renderer.hpp" #include "Cubed/scene/scene_manager.hpp" +#include "Cubed/tools/time_tools.hpp" namespace Cubed { WorldScene::WorldScene(SceneManager& scene_manager) : m_scene_manager(scene_manager), m_dev_panel(*this), @@ -380,7 +381,16 @@ bool WorldScene::handle_key_event(const KeyEvent& e) { } } } - + if (e.key == Key::F2 && e.action == KeyAction::PRESS) { + m_scene_manager.app().renderer().save_screenshot(); + ChatMessage msg; + msg.system_msg = true; + msg.color = Color::WHITE; + msg.text = "Saved Screenshot!"; + msg.time = Tools::get_time_ticks(); + m_hud_ui.add_chat_message(msg); + return true; + } if (m_paused) { switch (m_paused_ui) { case PauseUI::INVENTORY: