mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feature: screenshot (#39)
* build: add stb image write lib * feat(renderer): add screenshot capture with F2 * feat(screenshot): add screenshot viewer scene Add SCREENSHOT scene and UI to browse screenshots from the main menu, with localization for English and Chinese. Also allow image loading by full path and replace scene-operation asserts with error logs. * feat(ui): handle window resize in ScreenshotUI * feat(ui): add ScrollView widget and dynamic layout on resize Introduces a ScrollView widget with mouse wheel support and viewport clipping. Credits and screenshot screens now use it and recompute layout on window resize. Offset storage switched from ivec2 to vec2 with new accessors. * feat(ui): add lightbox viewer for screenshots Add a lightbox to preview screenshots on click. Introduce Button::set_texture for image-backed buttons, add widget getters for window size and visibility, and block background input while the lightbox is open. Close the lightbox with Escape or a left-click. * feat(ui): add screenshot button to pause menu Add a button to open the screenshot scene from the pause menu. Also enable linear filtering on screenshot textures for smoother scaling. * feat(ui): add show in file manager button to screenshot view - Add Tools::open_file_manager helper with Windows and Linux support. - Ensure screenshot directory is created before scanning. - Add localization keys for en_US and zh_CN. * feat(screenshot-ui): add newest/oldest sort selector Add a combo button to the screenshot gallery to sort files by modification time (newest or oldest first). Store timestamp per image and rebuild layout when sort order changes. Include translations for en_US and zh_CN. * fix: correct argument typo and path/error handling Fix --enable-consolelog flag, screenshot filter bug, paths to C APIs, add includes and gitignore entries, and improve ShellExecuteW failure detection. * fix(audio): improve source management and OpenAL diagnostics Fix null deref when source pool is full, initialize m_using, and improve source state handling. Add OpenAL vendor/version/renderer logging and correct voice PCM span type. * fix(client_entity_manager): store find result before assert * fix(tools): switch datetime format to underscore-separated Use %Y-%m-%d_%H-%M-%S instead of %F %T to avoid colons and spaces, making output suitable for file names. * fix: initialize uninitialized member variables Add default member initializers across various classes to prevent undefined behavior from uninitialized fields, and initialize the neighbor biome array in the chunk generator. * feat(texture_manager): add check_exist option for image loading Add a `check_exist` parameter to `get_image_texture` and `load_image_texture`, enabling callers to skip file existence checks. Log an error and return nullptr when image data fails to load. Update screenshot UI to support uppercase image extensions and gracefully ignore unreadable images.
This commit is contained in:
@@ -62,7 +62,7 @@ private:
|
||||
OpusDecoder* m_decoder{nullptr};
|
||||
AudioRecording m_recording;
|
||||
std::weak_ptr<NetworkClient> m_client;
|
||||
glm::vec3 listener_pos;
|
||||
glm::vec3 listener_pos{0.0f};
|
||||
std::unique_ptr<AudioSource> m_bgm;
|
||||
FadeMap m_fade_map;
|
||||
SoundManager m_sounds;
|
||||
|
||||
@@ -49,6 +49,6 @@ private:
|
||||
ALuint m_source = 0;
|
||||
float m_target_volume = 1.0f;
|
||||
float m_duration = 0.0f;
|
||||
bool m_using;
|
||||
bool m_using = false;
|
||||
};
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -18,12 +18,12 @@ private:
|
||||
THIRD_PERSON_FRONT,
|
||||
};
|
||||
|
||||
LocalPlayer* m_player;
|
||||
float m_last_mouse_x, m_last_mouse_y;
|
||||
glm::vec3 m_camera_pos;
|
||||
LocalPlayer* m_player = nullptr;
|
||||
float m_last_mouse_x = 0.0f, m_last_mouse_y = 0.0f;
|
||||
glm::vec3 m_camera_pos{0.0f};
|
||||
bool m_under_water = false;
|
||||
Perspective m_perspective = Perspective::FIRST_PERSON;
|
||||
glm::vec3 m_front;
|
||||
glm::vec3 m_front{0.0f};
|
||||
glm::vec3 camera_collision(glm::vec3 start, glm::vec3 end,
|
||||
float radius = 0.2f);
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ private:
|
||||
WorldScene& m_world_scene;
|
||||
Config& m_config;
|
||||
ConfigView m_config_view;
|
||||
LocalPlayer* m_player;
|
||||
LocalPlayer* m_player = nullptr;
|
||||
PlayerProfile m_player_profile;
|
||||
bool m_need_save_config = false;
|
||||
bool m_gen_thread_running = true;
|
||||
|
||||
@@ -22,7 +22,7 @@ struct Block : public BlockTexture {};
|
||||
|
||||
struct BlockRenderData {
|
||||
std::vector<bool> draw_face;
|
||||
unsigned block_id;
|
||||
unsigned block_id = 0;
|
||||
BlockRenderData() = default;
|
||||
BlockRenderData(const BlockRenderData&) = default;
|
||||
BlockRenderData& operator=(const BlockRenderData&) = default;
|
||||
|
||||
@@ -14,18 +14,18 @@
|
||||
namespace Cubed {
|
||||
class ClientWorld;
|
||||
struct ChunkRenderSnapshot {
|
||||
GLuint normal_vao;
|
||||
size_t normal_vertices_count;
|
||||
GLuint cross_vao;
|
||||
size_t cross_vertices_count;
|
||||
GLuint normal_discard_vao;
|
||||
size_t normal_discard_vertices_count;
|
||||
GLuint normal_blend_vao;
|
||||
size_t normal_blend_vertices_count;
|
||||
GLuint water_vao;
|
||||
size_t water_vertices_count;
|
||||
glm::vec3 center;
|
||||
glm::vec3 half_extents;
|
||||
GLuint normal_vao = 0;
|
||||
size_t normal_vertices_count = 0;
|
||||
GLuint cross_vao = 0;
|
||||
size_t cross_vertices_count = 0;
|
||||
GLuint normal_discard_vao = 0;
|
||||
size_t normal_discard_vertices_count = 0;
|
||||
GLuint normal_blend_vao = 0;
|
||||
size_t normal_blend_vertices_count = 0;
|
||||
GLuint water_vao = 0;
|
||||
size_t water_vertices_count = 0;
|
||||
glm::vec3 center{0.0f};
|
||||
glm::vec3 half_extents{0.0f};
|
||||
};
|
||||
class ClientChunk : public Chunk {
|
||||
public:
|
||||
@@ -98,7 +98,7 @@ private:
|
||||
std::atomic<bool> m_is_on_gen_vertex_data{false};
|
||||
std::atomic<BiomeType> m_biome = BiomeType::PLAIN;
|
||||
std::mutex m_vertexs_data_mutex;
|
||||
ChunkPos m_chunk_pos;
|
||||
ChunkPos m_chunk_pos{0, 0};
|
||||
ClientWorld& m_world;
|
||||
// the index is a array of block id
|
||||
std::vector<BlockType> m_blocks;
|
||||
@@ -111,7 +111,7 @@ private:
|
||||
*/
|
||||
std::vector<VertexData> m_vertex_data;
|
||||
|
||||
ChunkRenderSnapshot m_render_snapshot;
|
||||
ChunkRenderSnapshot m_render_snapshot{};
|
||||
|
||||
unsigned m_seed = 0;
|
||||
void clear_dirty();
|
||||
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
private:
|
||||
struct VoiceMessage {
|
||||
std::string data;
|
||||
glm::vec3 pos;
|
||||
glm::vec3 pos{0.0f};
|
||||
};
|
||||
|
||||
std::atomic<bool> m_is_pending_delete_queue_free{false};
|
||||
@@ -127,7 +127,7 @@ private:
|
||||
|
||||
struct PendingSound {
|
||||
std::string sound;
|
||||
glm::vec3 sound_pos;
|
||||
glm::vec3 sound_pos{0.0f};
|
||||
};
|
||||
|
||||
static constexpr int WORLD_EXIT_TIMEOUT = 200;
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
namespace Cubed {
|
||||
struct BaseClientCreature {
|
||||
|
||||
Transform transform;
|
||||
Transform transform{};
|
||||
|
||||
WalkPose pose;
|
||||
WalkPose pose{};
|
||||
|
||||
ModelID model;
|
||||
ModelID model = 0;
|
||||
};
|
||||
|
||||
struct SoundTime {
|
||||
float next_call_time;
|
||||
float next_call_time = 0.0f;
|
||||
};
|
||||
|
||||
struct ClientEntitySnapshot {
|
||||
|
||||
@@ -67,7 +67,7 @@ private:
|
||||
|
||||
ChunkPos m_chunk_pos;
|
||||
ServerWorld& m_world;
|
||||
HeightMapArray m_heightmap;
|
||||
HeightMapArray m_heightmap{};
|
||||
// the index is a array of block id
|
||||
std::vector<BlockType> m_blocks;
|
||||
OptionalBlockVectorArray m_neightbor_blocks;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <tbb/concurrent_hash_map.h>
|
||||
#include <tbb/concurrent_queue.h>
|
||||
#include <tbb/concurrent_vector.h>
|
||||
#include <variant>
|
||||
namespace Cubed {
|
||||
class ServerWorld;
|
||||
class Session;
|
||||
|
||||
@@ -59,7 +59,7 @@ private:
|
||||
std::atomic<int> m_chunk_task_id{0};
|
||||
std::atomic<float> m_yaw{0.0f};
|
||||
std::atomic<float> m_pitch{0.0f};
|
||||
std::atomic<Gait> m_gait;
|
||||
std::atomic<Gait> m_gait{Gait::STOP};
|
||||
mutable std::shared_mutex m_chunk_pos_mutex;
|
||||
ChunkPosSet m_player_chunk_pos_set;
|
||||
};
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
private:
|
||||
enum class ChunkState { NONE, GENERATING, READY, PENDING_DELETE };
|
||||
struct ChunkEntity {
|
||||
ChunkState state;
|
||||
ChunkState state = ChunkState::NONE;
|
||||
std::shared_ptr<ServerChunk> chunk;
|
||||
std::atomic<uint32_t> ref_count = 0;
|
||||
ChunkEntity() = default;
|
||||
|
||||
@@ -24,8 +24,8 @@ private:
|
||||
float tx = 0.0f, ty = 0.0f, tz = 0.0f;
|
||||
};
|
||||
Renderer& m_renderer;
|
||||
std::array<GLuint, BODY_PART_NUM> m_vao;
|
||||
std::array<GLuint, BODY_PART_NUM> m_vbo;
|
||||
std::array<GLuint, BODY_PART_NUM> m_vao{};
|
||||
std::array<GLuint, BODY_PART_NUM> m_vbo{};
|
||||
bool m_inited{false};
|
||||
std::array<std::vector<PlayerVertex>, BODY_PART_NUM> m_vertices;
|
||||
};
|
||||
|
||||
@@ -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,7 +100,9 @@ private:
|
||||
float m_window_width = 0.0f;
|
||||
float m_window_height = 0.0f;
|
||||
|
||||
glm::mat4 m_world_proj_matrix;
|
||||
bool m_save_screenshot = false;
|
||||
|
||||
glm::mat4 m_world_proj_matrix{0.0f};
|
||||
|
||||
std::unique_ptr<VertexBuffer> m_sky_vbo;
|
||||
std::unique_ptr<VertexBuffer> m_outline_indices_vbo;
|
||||
@@ -107,7 +111,7 @@ private:
|
||||
std::unique_ptr<VertexBuffer> m_player_vbo;
|
||||
std::unique_ptr<VertexBuffer> m_quad_vbo;
|
||||
|
||||
glm::mat4 m_ui_proj_matrix;
|
||||
glm::mat4 m_ui_proj_matrix{0.0f};
|
||||
ShaderManager m_shaders;
|
||||
|
||||
/*
|
||||
@@ -129,6 +133,7 @@ private:
|
||||
void updata_framebuffer(int width, int height);
|
||||
void init_quad();
|
||||
void init_text();
|
||||
void handle_screenshot();
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -89,8 +89,8 @@ private:
|
||||
std::unique_ptr<FrameBuffer> m_depth_map_fbo;
|
||||
std::unique_ptr<Texture> m_depth_map_texture;
|
||||
|
||||
glm::vec3 m_blend_from_lightdir;
|
||||
glm::vec3 m_blend_to_lightdir;
|
||||
glm::vec3 m_blend_from_lightdir{0.0f};
|
||||
glm::vec3 m_blend_to_lightdir{0.0f};
|
||||
float m_blend_t = 1.0f;
|
||||
bool m_blend_initialized = false;
|
||||
static constexpr float BLEND_DURATION = 0.15f;
|
||||
@@ -125,7 +125,7 @@ private:
|
||||
ParallelLight m_parallel_light;
|
||||
SkyUniform m_sky_uniform;
|
||||
|
||||
glm::mat4 view_matrix;
|
||||
glm::mat4 view_matrix{0.0f};
|
||||
|
||||
const TextureManager& m_texture_manager;
|
||||
void day_night_calculation(ClientWorld& world);
|
||||
|
||||
@@ -9,7 +9,8 @@ enum class SceneType {
|
||||
CREDITS,
|
||||
SETTINGS,
|
||||
HOST_GAME,
|
||||
JOIN_GAME
|
||||
JOIN_GAME,
|
||||
SCREENSHOT
|
||||
};
|
||||
|
||||
class Scene {
|
||||
|
||||
29
include/Cubed/scene/screenshot_scene.hpp
Normal file
29
include/Cubed/scene/screenshot_scene.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "Cubed/scene/scene.hpp"
|
||||
#include "Cubed/ui/screenshot_ui.hpp"
|
||||
namespace Cubed {
|
||||
class SceneManager;
|
||||
class ScreenshotScene : public Scene {
|
||||
public:
|
||||
ScreenshotScene(SceneManager& scene_manager);
|
||||
~ScreenshotScene();
|
||||
|
||||
ScreenshotScene(const ScreenshotScene&) = delete;
|
||||
ScreenshotScene(ScreenshotScene&&) = delete;
|
||||
ScreenshotScene& operator=(const ScreenshotScene&) = delete;
|
||||
ScreenshotScene& operator=(ScreenshotScene&&) = delete;
|
||||
|
||||
void update(float dt) override;
|
||||
void render(Renderer& renderer) override;
|
||||
bool handle_event(const Event& e) override;
|
||||
void on_enter() override;
|
||||
void on_leave() override;
|
||||
void on_re_enter() override;
|
||||
|
||||
SceneManager& scene_manager();
|
||||
|
||||
private:
|
||||
SceneManager& m_scene_manager;
|
||||
ScreenshotUI m_ui;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
WorldUIManager m_hud_ui;
|
||||
ErrorUI m_error_ui;
|
||||
const Argument& m_argument;
|
||||
VoiceInputType m_input_type;
|
||||
VoiceInputType m_input_type = VoiceInputType::OFF;
|
||||
RunMode m_runmode = RunMode::HYBRID;
|
||||
bool handle_mouse_move_event(const MouseMoveEvent& e) override;
|
||||
bool handle_mouse_button_event(const MouseButtonEvent& e) override;
|
||||
|
||||
@@ -20,7 +20,9 @@ public:
|
||||
const Texture* get_block_status_array() const;
|
||||
const Texture* get_texture_array() const;
|
||||
const Texture* get_cross_plane_array() const;
|
||||
const Texture* get_image_texture(const std::string& path);
|
||||
const Texture* get_image_texture(const std::string& path,
|
||||
bool full_path = false,
|
||||
bool check_exist = true);
|
||||
const Texture* get_pbr_texture() const;
|
||||
const ItemTextureMap& get_item_textures() const;
|
||||
const Texture* get_skin() const;
|
||||
@@ -49,7 +51,9 @@ private:
|
||||
void load_block_texture(unsigned block_id);
|
||||
void init_item_texture();
|
||||
void load_cross_plane_texture(unsigned id);
|
||||
const Texture* load_image_texture(const std::string& path);
|
||||
const Texture* load_image_texture(const std::string& path,
|
||||
bool full_path = false,
|
||||
bool check_exist = true);
|
||||
void load_pbr_texture(unsigned id);
|
||||
void init_item();
|
||||
void init_block();
|
||||
|
||||
66
include/Cubed/tools/file_utils.hpp
Normal file
66
include/Cubed/tools/file_utils.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
#ifdef _WIN32
|
||||
// clang-format off
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
// clang-format on
|
||||
#elif __linux__
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
namespace Cubed::Tools {
|
||||
|
||||
inline void open_file_manager(const std::filesystem::path& path) {
|
||||
#ifdef _WIN32
|
||||
auto abs_path = std::filesystem::absolute(path);
|
||||
if (!std::filesystem::exists(abs_path)) {
|
||||
Logger::warn("Path does not exist: {}", abs_path.string());
|
||||
return;
|
||||
}
|
||||
HINSTANCE result =
|
||||
ShellExecuteW(nullptr, L"open", abs_path.wstring().c_str(), nullptr,
|
||||
nullptr, SW_SHOWNORMAL);
|
||||
if ((INT_PTR)result <= 32) {
|
||||
Logger::warn("ShellExecuteW failed for path: {}, error code: {}",
|
||||
path.string(), (int)(INT_PTR)result);
|
||||
}
|
||||
|
||||
#elif __linux__
|
||||
|
||||
constexpr const char* FILE_MANAGERS[] = {"nautilus", "dolphin", "thunar",
|
||||
"nemo", "pcmanfm"};
|
||||
|
||||
auto is_available = [](const char* exe) {
|
||||
std::string cmd = std::string("command -v ") + exe + " >/dev/null 2>&1";
|
||||
return std::system(cmd.c_str()) == 0;
|
||||
};
|
||||
|
||||
const std::string QUOTED = "\"" + path.string() + "\"";
|
||||
for (const char* fm : FILE_MANAGERS) {
|
||||
if (!is_available(fm)) {
|
||||
continue;
|
||||
}
|
||||
std::string cmd = std::string(fm) + " " + QUOTED + " >/dev/null 2>&1 &";
|
||||
if (std::system(cmd.c_str()) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: let the system choose a handler.
|
||||
if (is_available("xdg-open")) {
|
||||
std::string cmd = "xdg-open " + QUOTED + " >/dev/null 2>&1 &";
|
||||
if (std::system(cmd.c_str()) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Logger::warn("Failed to open file manager for {}", path.string());
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Cubed::Tools
|
||||
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Cubed {
|
||||
class SensitiveFilter {
|
||||
public:
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL_timer.h>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <string>
|
||||
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<std::chrono::seconds>(zone->to_local(now));
|
||||
return std::format("{:%Y-%m-%d_%H-%M-%S}", local);
|
||||
}
|
||||
|
||||
} // namespace Tools
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
Button& set_background_image(const std::string& path,
|
||||
TextureManager& texture_manager);
|
||||
Button& set_default_image(TextureManager& texture_manager);
|
||||
Button& set_texture(const Texture* texture, bool change_button_size);
|
||||
virtual Button& set_text(const std::string& text);
|
||||
|
||||
Button& set_auto_scale(bool auto_scale);
|
||||
|
||||
@@ -9,9 +9,11 @@ class CreditsUI : public UIManager {
|
||||
public:
|
||||
CreditsUI(CreditsScene& m_scene);
|
||||
void init() override;
|
||||
void update_layout(int width, int height);
|
||||
|
||||
private:
|
||||
bool handle_key_event(const KeyEvent& e) override;
|
||||
bool handle_window_resize_event(const WindowResizeEvent& e) override;
|
||||
CreditsScene& m_scene;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -13,7 +13,7 @@ public:
|
||||
|
||||
private:
|
||||
HostGameScene& m_scene;
|
||||
Label* m_error_label;
|
||||
Label* m_error_label = nullptr;
|
||||
void set_error(std::string_view error);
|
||||
void clear_error();
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@ private:
|
||||
void on_update(float dt) override;
|
||||
std::unique_ptr<Image> m_background;
|
||||
std::unique_ptr<Image> m_foreground;
|
||||
ItemID m_id;
|
||||
ItemID m_id = 0;
|
||||
float m_scale = 1.0f;
|
||||
bool m_hovered = false;
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
|
||||
private:
|
||||
JoinGameScene& m_scene;
|
||||
Label* m_error_label;
|
||||
Label* m_error_label = nullptr;
|
||||
void set_error(std::string_view error);
|
||||
void clear_error();
|
||||
};
|
||||
|
||||
49
include/Cubed/ui/screenshot_ui.hpp
Normal file
49
include/Cubed/ui/screenshot_ui.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/ui/image.hpp"
|
||||
#include "Cubed/ui/ui_manager.hpp"
|
||||
|
||||
#include <chrono>
|
||||
namespace Cubed {
|
||||
class Texture;
|
||||
class ScreenshotScene;
|
||||
class ScreenshotUI : public UIManager {
|
||||
public:
|
||||
ScreenshotUI(ScreenshotScene& m_scene);
|
||||
~ScreenshotUI();
|
||||
|
||||
ScreenshotUI(const ScreenshotUI&) = delete;
|
||||
ScreenshotUI(ScreenshotUI&&) = delete;
|
||||
ScreenshotUI& operator=(const ScreenshotUI&) = delete;
|
||||
ScreenshotUI& operator=(ScreenshotUI&&) = delete;
|
||||
|
||||
void init() override;
|
||||
|
||||
void update_layout(int width, int height);
|
||||
|
||||
void open_lightbox(const Texture* image);
|
||||
void update(float dt) override;
|
||||
|
||||
private:
|
||||
struct ImageInfo {
|
||||
const Texture* texture = nullptr;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
std::chrono::nanoseconds time{0};
|
||||
};
|
||||
|
||||
enum class SortType { NEWEST_FIRST, OLDEST_FIRST };
|
||||
|
||||
ScreenshotScene& m_scene;
|
||||
std::vector<ImageInfo> m_image_infos;
|
||||
SortType m_sort_type = SortType::NEWEST_FIRST;
|
||||
bool m_need_rebuild = false;
|
||||
Widget* m_lightbox = nullptr;
|
||||
Image* m_lightbox_image = nullptr;
|
||||
bool handle_window_resize_event(const WindowResizeEvent& e) override;
|
||||
bool handle_key_event(const KeyEvent& e) override;
|
||||
bool handle_mouse_button_event(const MouseButtonEvent& e) override;
|
||||
bool handle_mouse_move_event(const MouseMoveEvent& e) override;
|
||||
bool handle_mouse_wheel_event(const MouseWheelEvent& e) override;
|
||||
};
|
||||
} // namespace Cubed
|
||||
35
include/Cubed/ui/scroll_view.hpp
Normal file
35
include/Cubed/ui/scroll_view.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
namespace Cubed {
|
||||
class ColumnLayout;
|
||||
class ScrollView : public Widget {
|
||||
public:
|
||||
ScrollView(const ScrollView&) = delete;
|
||||
ScrollView(ScrollView&&) = delete;
|
||||
ScrollView& operator=(const ScrollView&) = delete;
|
||||
ScrollView& operator=(ScrollView&&) = delete;
|
||||
|
||||
ScrollView(Widget* parent);
|
||||
~ScrollView();
|
||||
|
||||
void render(Renderer& renderer) override;
|
||||
|
||||
float width() const override;
|
||||
// visable height, you need notice offset
|
||||
float height() const override;
|
||||
|
||||
ScrollView& set_child(std::unique_ptr<ColumnLayout> children);
|
||||
|
||||
bool handle_mouse_wheel_event(const MouseWheelEvent& e) override;
|
||||
bool handle_mouse_move_event(const MouseMoveEvent& e) override;
|
||||
Widget& set_fill_parent(bool fill) override;
|
||||
Widget& set_fill_width(bool fill) override;
|
||||
Widget& set_fill_height(bool fill) override;
|
||||
|
||||
private:
|
||||
ColumnLayout* m_child = nullptr;
|
||||
bool m_hovered = false;
|
||||
float m_scroll_speed = 50.0f;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -28,12 +28,19 @@ public:
|
||||
Widget& operator=(Widget&&) = delete;
|
||||
|
||||
Widget(Widget* parent);
|
||||
|
||||
static void set_window_size(int width, int height);
|
||||
static int get_window_height();
|
||||
static int get_window_width();
|
||||
|
||||
virtual ~Widget() = default;
|
||||
virtual void update(float dt);
|
||||
virtual void render(Renderer& renderer);
|
||||
virtual Widget& set_anchor(Anchor anchor);
|
||||
virtual Widget& set_offset(glm::ivec2 offset);
|
||||
static void set_window_size(int width, int height);
|
||||
virtual Widget& set_offset(glm::vec2 offset);
|
||||
virtual Widget& add_offset(glm::vec2 offset);
|
||||
virtual glm::vec2 get_offset() const;
|
||||
|
||||
virtual Widget& set_visible(bool visible);
|
||||
// Returns the final display size
|
||||
|
||||
@@ -56,6 +63,8 @@ public:
|
||||
virtual bool handle_window_resize_event(const WindowResizeEvent& e);
|
||||
virtual bool handle_mouse_move_event(const MouseMoveEvent& e);
|
||||
virtual bool handle_text_input_event(const TextInputEvent& e);
|
||||
|
||||
virtual bool is_visible() const;
|
||||
void set_order(TraversalOrder order);
|
||||
|
||||
template <typename T, typename... Args> T& add_child(Args&&... args) {
|
||||
@@ -78,7 +87,7 @@ protected:
|
||||
bool m_fill_width = false;
|
||||
bool m_show_border = false;
|
||||
int m_border_size = 5;
|
||||
glm::ivec2 m_offset{0, 0};
|
||||
glm::vec2 m_offset{0, 0};
|
||||
|
||||
std::vector<std::unique_ptr<Widget>>& children();
|
||||
|
||||
@@ -101,7 +110,7 @@ private:
|
||||
*/
|
||||
std::array<std::unique_ptr<Widget>, 4> m_border;
|
||||
TraversalOrder m_order = TraversalOrder::BACK_TO_FRONT;
|
||||
glm::vec2 m_mouse_pos;
|
||||
glm::vec2 m_mouse_pos{0.0f};
|
||||
float m_width = 0.0f;
|
||||
float m_height = 0.0f;
|
||||
};
|
||||
|
||||
@@ -50,8 +50,8 @@ private:
|
||||
bool m_imgui_init = false;
|
||||
bool m_game_running = false;
|
||||
bool m_enable_exclusive = false;
|
||||
SDL_Window* m_window;
|
||||
SDL_GLContext m_context;
|
||||
SDL_Window* m_window = nullptr;
|
||||
SDL_GLContext m_context = nullptr;
|
||||
int m_window_width = 0;
|
||||
int m_window_height = 0;
|
||||
SDL_DisplayID m_windowed_display = 0;
|
||||
|
||||
Reference in New Issue
Block a user