From 453eac7f1f5ef70390ec51087fc1f190811a7507 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 17 Nov 2021 09:47:45 +0100 Subject: Replace sfml with mgl --- src/AsyncImageLoader.cpp | 65 +- src/Body.cpp | 413 ++++----- src/BodyItem.cpp | 7 +- src/DownloadUtils.cpp | 20 +- src/Downloader.cpp | 12 +- src/Entry.cpp | 67 +- src/FileAnalyzer.cpp | 2 +- src/ImageViewer.cpp | 211 +++-- src/NetUtils.cpp | 45 - src/QuickMedia.cpp | 1415 ++++++++++++++--------------- src/ResourceLoader.cpp | 60 +- src/RoundedRectangle.cpp | 61 +- src/SearchBar.cpp | 201 ++-- src/SfmlFixes.cpp | 15 - src/Tabs.cpp | 155 ++-- src/Text.cpp | 590 +++++++----- src/Theme.cpp | 4 +- src/Utils.cpp | 4 +- src/VideoPlayer.cpp | 24 +- src/gui/Button.cpp | 51 +- src/plugins/AniList.cpp | 3 +- src/plugins/FileManager.cpp | 4 +- src/plugins/Fourchan.cpp | 8 +- src/plugins/ImageBoard.cpp | 5 +- src/plugins/Info.cpp | 5 +- src/plugins/Matrix.cpp | 36 +- src/plugins/MediaGeneric.cpp | 4 +- src/plugins/MyAnimeList.cpp | 4 +- src/plugins/NyaaSi.cpp | 8 +- src/plugins/Page.cpp | 9 +- src/plugins/Saucenao.cpp | 2 +- src/plugins/Youtube.cpp | 8 +- src/plugins/youtube/YoutubeMediaProxy.cpp | 3 +- 33 files changed, 1761 insertions(+), 1760 deletions(-) delete mode 100644 src/SfmlFixes.cpp (limited to 'src') diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp index 4661960..c1d4aab 100644 --- a/src/AsyncImageLoader.cpp +++ b/src/AsyncImageLoader.cpp @@ -3,7 +3,6 @@ #include "../include/Program.hpp" #include "../include/ImageUtils.hpp" #include "../include/Scale.hpp" -#include "../include/SfmlFixes.hpp" #include "../include/Utils.hpp" #include "../external/hash-library/sha256.h" @@ -22,13 +21,16 @@ #define STB_IMAGE_RESIZE_IMPLEMENTATION #include "../external/stb/stb_image_resize.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "../external/stb/stb_image_write.h" + namespace QuickMedia { static bool webp_to_png(const Path &thumbnail_path, const Path &destination_path) { const char *args[] = { "ffmpeg", "-y", "-v", "quiet", "-i", thumbnail_path.data.c_str(), "--", destination_path.data.c_str(), nullptr}; return exec_program(args, nullptr, nullptr) == 0; } - bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, sf::Vector2i resize_target_size, ContentType content_type, bool symlink_if_no_resize) { + bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, mgl::vec2i resize_target_size, ContentType content_type, bool symlink_if_no_resize) { Path input_path = thumbnail_path; if(content_type == ContentType::IMAGE_WEBP) { @@ -56,8 +58,8 @@ namespace QuickMedia { if(getppid() != parent_pid) _exit(127); - sf::Image image; - if(!image.loadFromFile(input_path.data) || image.getSize().x == 0 || image.getSize().y == 0) { + mgl::Image image; + if(!image.load_from_file(input_path.data.c_str()) || image.get_size().x == 0 || image.get_size().y == 0) { fprintf(stderr, "Failed to load %s\n", input_path.data.c_str()); _exit(1); } @@ -65,7 +67,7 @@ namespace QuickMedia { Path result_path_tmp = thumbnail_path_resized; result_path_tmp.append(".tmp.png"); - if(image.getSize().x <= (unsigned int)resize_target_size.x && image.getSize().y <= (unsigned int)resize_target_size.y) { + if(image.get_size().x <= resize_target_size.x && image.get_size().y <= resize_target_size.y) { if(content_type == ContentType::IMAGE_WEBP) { if(rename_atomic(input_path.data.c_str(), thumbnail_path_resized.data.c_str()) == 0) _exit(0); @@ -109,17 +111,24 @@ namespace QuickMedia { close(output_file); } } else { - sf::Vector2u clamped_size = clamp_to_size(image.getSize(), sf::Vector2u(resize_target_size.x, resize_target_size.y)); - unsigned char *output_pixels = new unsigned char[clamped_size.x * clamped_size.y * 4]; - stbir_resize_uint8(image.getPixelsPtr(), image.getSize().x, image.getSize().y, 0, output_pixels, clamped_size.x, clamped_size.y, 0, 4); - - // TODO: Remove this and use stb write to remove this unecessary extra copy of the data and write the data directly to file after converting it to png - sf::Image destination_image; - destination_image.create(clamped_size.x, clamped_size.y, output_pixels); - if(!destination_image.saveToFile(result_path_tmp.data)) { - fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); - _exit(1); + mgl::vec2i clamped_size = clamp_to_size(image.get_size(), mgl::vec2i(resize_target_size.x, resize_target_size.y)); + unsigned char *output_pixels = new unsigned char[clamped_size.x * clamped_size.y * image.get_num_channels()]; + stbir_resize_uint8(image.data(), image.get_size().x, image.get_size().y, 0, output_pixels, clamped_size.x, clamped_size.y, 0, image.get_num_channels()); + + if(image.get_num_channels() == 4) { + if(!stbi_write_png(result_path_tmp.data.c_str(), clamped_size.x, clamped_size.y, 4, output_pixels, 0)) { + fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); + _exit(1); + } + } else { + if(!stbi_write_jpg(result_path_tmp.data.c_str(), clamped_size.x, clamped_size.y, image.get_num_channels(), output_pixels, 0)) { + fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); + _exit(1); + } } + + // TODO: Resize and save to dxt format which can be loaded faster, uses less memory during loading (since no conversion is needed to upload to gpu), + // it uses less memory while in gpu (because its in dxt compressed format) and it gives better rendering performance because of compressed image = smaller = better cache utilization. } if(rename_atomic(result_path_tmp.data.c_str(), thumbnail_path_resized.data.c_str()) == 0) @@ -147,11 +156,11 @@ namespace QuickMedia { return true; } - void AsyncImageLoader::load_create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, ThumbnailData *thumbnail_data, sf::Vector2i resize_target_size) { + void AsyncImageLoader::load_create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, ThumbnailData *thumbnail_data, mgl::vec2i resize_target_size) { FileAnalyzer file_analyzer; if(!file_analyzer.load_file(thumbnail_path.data.c_str(), false)) { fprintf(stderr, "Failed to convert %s to a thumbnail\n", thumbnail_path.data.c_str()); - thumbnail_data->image = std::make_unique(); + thumbnail_data->image = std::make_unique(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; return; } @@ -161,7 +170,7 @@ namespace QuickMedia { thumbnail_data->loading_state = LoadingState::READY_TO_LOAD; } else { fprintf(stderr, "Failed to get first frame of %s\n", thumbnail_path.data.c_str()); - thumbnail_data->image = std::make_unique(); + thumbnail_data->image = std::make_unique(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; } return; @@ -171,7 +180,7 @@ namespace QuickMedia { thumbnail_data->loading_state = LoadingState::READY_TO_LOAD; } else { fprintf(stderr, "Failed to convert %s to a thumbnail\n", thumbnail_path.data.c_str()); - thumbnail_data->image = std::make_unique(); + thumbnail_data->image = std::make_unique(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; } } @@ -190,7 +199,7 @@ namespace QuickMedia { if(get_file_type(thumbnail_path_resized) == FileType::REGULAR) { fprintf(stderr, "Loaded %s from thumbnail cache\n", thumbnail_path_resized.data.c_str()); - thumbnail_load_data.thumbnail_data->image = std::make_unique(); + thumbnail_load_data.thumbnail_data->image = std::make_unique(); thumbnail_load_data.thumbnail_data->loading_state = LoadingState::READY_TO_LOAD; return; } @@ -208,14 +217,14 @@ namespace QuickMedia { } static void load_processed_thumbnail(ThumbnailLoadData &thumbnail_load_data) { - thumbnail_load_data.thumbnail_data->image = std::make_unique(); + thumbnail_load_data.thumbnail_data->image = std::make_unique(); Path thumbnail_path_resized = thumbnail_load_data.thumbnail_path; if(thumbnail_load_data.resize_target_size.x != 0 && thumbnail_load_data.resize_target_size.y != 0) thumbnail_path_resized.append("_" + std::to_string(thumbnail_load_data.resize_target_size.x) + "x" + std::to_string(thumbnail_load_data.resize_target_size.y)); if(get_file_type(thumbnail_path_resized) == FileType::REGULAR) { - load_image_from_file(*thumbnail_load_data.thumbnail_data->image, thumbnail_path_resized.data); + thumbnail_load_data.thumbnail_data->image->load_from_file(thumbnail_path_resized.data.c_str()); thumbnail_load_data.thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; return; } @@ -227,10 +236,10 @@ namespace QuickMedia { thumbnail_original_path = thumbnail_load_data.thumbnail_path; if(thumbnail_load_data.resize_target_size.x != 0 && thumbnail_load_data.resize_target_size.y != 0) { - load_image_from_file(*thumbnail_load_data.thumbnail_data->image, thumbnail_path_resized.data); + thumbnail_load_data.thumbnail_data->image->load_from_file(thumbnail_path_resized.data.c_str()); thumbnail_load_data.thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; } else { - load_image_from_file(*thumbnail_load_data.thumbnail_data->image, thumbnail_original_path.data); + thumbnail_load_data.thumbnail_data->image->load_from_file(thumbnail_original_path.data.c_str()); thumbnail_load_data.thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; } } @@ -304,12 +313,12 @@ namespace QuickMedia { return exec_program_pipe(args, read_program) == 0; } - bool AsyncImageLoader::load_thumbnail(const std::string &url, bool local, sf::Vector2i resize_target_size, std::shared_ptr thumbnail_data, Path &thumbnail_path) { + bool AsyncImageLoader::load_thumbnail(const std::string &url, bool local, mgl::vec2i resize_target_size, std::shared_ptr thumbnail_data, Path &thumbnail_path) { if(thumbnail_data->loading_state != LoadingState::NOT_LOADED) return true; if(url.empty()) { - thumbnail_data->image = std::make_unique(); + thumbnail_data->image = std::make_unique(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; return false; } @@ -319,7 +328,7 @@ namespace QuickMedia { memset(&file_stat, 0, sizeof(file_stat)); if(stat(url.c_str(), &file_stat) != 0 || !S_ISREG(file_stat.st_mode)) { fprintf(stderr, "Failed to load thumbnail %s: no such file\n", url.c_str()); - thumbnail_data->image = std::make_unique(); + thumbnail_data->image = std::make_unique(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; return false; } @@ -357,7 +366,7 @@ namespace QuickMedia { return true; } - std::shared_ptr AsyncImageLoader::get_thumbnail(const std::string &url, bool local, sf::Vector2i resize_target_size) { + std::shared_ptr AsyncImageLoader::get_thumbnail(const std::string &url, bool local, mgl::vec2i resize_target_size) { // TODO: Instead of generating a new hash everytime to access thumbnail, cache the hash of the thumbnail url auto &thumbnail_data = thumbnails[url]; if(!thumbnail_data) diff --git a/src/Body.cpp b/src/Body.cpp index eb7a1be..d8e4acd 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -6,12 +6,12 @@ #include "../include/Utils.hpp" #include "../include/Theme.hpp" #include "../include/StringUtils.hpp" +#include #include "../plugins/Plugin.hpp" #include -#include -#include -#include -#include +#include +#include +#include #include #include #include @@ -41,7 +41,7 @@ namespace QuickMedia { static const int card_padding_x = 20 * get_config().scale; static const int card_padding_y = 20 * get_config().scale; static const int card_image_text_padding = 10 * get_config().scale; - static const sf::Vector2i card_max_image_size(card_width - card_padding_x * 2, (card_height - card_padding_y * 2) / 2); + static const mgl::vec2i card_max_image_size(card_width - card_padding_x * 2, (card_height - card_padding_y * 2) / 2); static const int num_columns_switch_to_list = 1; static const int embedded_item_border_width = 4; @@ -82,7 +82,7 @@ namespace QuickMedia { body_spacing[BODY_THEME_MODERN_SPACIOUS].embedded_item_font_size = std::floor(get_config().body.embedded_load_font_size * get_config().scale * get_config().font_scale); } - static void init_body_themes() { + void init_body_themes() { if(themes_initialized) return; @@ -91,38 +91,31 @@ namespace QuickMedia { themes_initialized = true; } - static sf::Vector2f to_vec2f(const sf::Vector2i &vec) { - return sf::Vector2f(vec.x, vec.y); - } - - Body::Body(BodyTheme body_theme, sf::Texture &loading_icon_texture, sf::Shader *rounded_rectangle_shader, sf::Shader *rounded_rectangle_mask_shader) : + Body::Body(BodyTheme body_theme, mgl::Texture &loading_icon_texture, mgl::Shader *rounded_rectangle_shader, mgl::Shader *rounded_rectangle_mask_shader) : draw_thumbnails(true), body_item_render_callback(nullptr), thumbnail_mask_shader(nullptr), body_theme(body_theme), selected_item(0), prev_selected_item(0), - loading_icon(loading_icon_texture), - progress_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(get_config().body.progress_font_size * get_config().scale * get_config().font_scale)), - replies_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(get_config().body.replies_font_size * get_config().scale * get_config().font_scale)), + loading_icon(&loading_icon_texture), + progress_text("", *FontLoader::get_font(FontLoader::FontType::LATIN, get_config().body.progress_font_size * get_config().scale * get_config().font_scale)), + replies_text("", *FontLoader::get_font(FontLoader::FontType::LATIN, get_config().body.replies_font_size * get_config().scale * get_config().font_scale)), + embedded_item_load_text("", *FontLoader::get_font(FontLoader::FontType::LATIN, body_spacing[body_theme].embedded_item_font_size)), num_visible_items(0), top_cut_off(false), bottom_cut_off(false), - item_background(sf::Vector2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().selected_color, rounded_rectangle_shader), - reaction_background(sf::Vector2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().shade_color, rounded_rectangle_shader), + item_background(mgl::vec2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().selected_color, rounded_rectangle_shader), + reaction_background(mgl::vec2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().shade_color, rounded_rectangle_shader), rounded_rectangle_shader(rounded_rectangle_shader), rounded_rectangle_mask_shader(rounded_rectangle_mask_shader) { - assert(rounded_rectangle_shader); - assert(rounded_rectangle_mask_shader); - init_body_themes(); - embedded_item_load_text = sf::Text("", *FontLoader::get_font(FontLoader::FontType::LATIN), body_spacing[body_theme].embedded_item_font_size); - progress_text.setFillColor(get_theme().text_color); - replies_text.setFillColor(get_theme().replies_text_color); + progress_text.set_color(get_theme().text_color); + replies_text.set_color(get_theme().replies_text_color); thumbnail_max_size.x = 600; thumbnail_max_size.y = 337; - sf::Vector2f loading_icon_size(loading_icon.getTexture()->getSize().x, loading_icon.getTexture()->getSize().y); - loading_icon.setOrigin(loading_icon_size.x * 0.5f, loading_icon_size.y * 0.5f); + mgl::vec2f loading_icon_size(loading_icon.get_texture()->get_size().x, loading_icon.get_texture()->get_size().y); + loading_icon.set_origin(mgl::vec2f(loading_icon_size.x * 0.5f, loading_icon_size.y * 0.5f)); render_selected_item_bg = !is_touch_enabled(); } @@ -480,23 +473,23 @@ namespace QuickMedia { } } - bool Body::on_event(const sf::RenderWindow &window, const sf::Event &event, bool keyboard_navigation) { - if(keyboard_navigation && event.type == sf::Event::KeyPressed && !event.key.alt) { + bool Body::on_event(const mgl::Window &window, const mgl::Event &event, bool keyboard_navigation) { + if(keyboard_navigation && event.type == mgl::Event::KeyPressed && !event.key.alt) { const bool rendering_card_view = card_view && card_view_enabled; - if(event.key.code == sf::Keyboard::Up || (event.key.control && event.key.code == sf::Keyboard::K)) { + if(event.key.code == mgl::Keyboard::Up || (event.key.control && event.key.code == mgl::Keyboard::K)) { render_selected_item_bg = true; bool top_reached = select_previous_item(true); if(!top_reached && on_top_reached) on_top_reached(); return true; - } else if(event.key.code == sf::Keyboard::Down || (event.key.control && event.key.code == sf::Keyboard::J)) { + } else if(event.key.code == mgl::Keyboard::Down || (event.key.control && event.key.code == mgl::Keyboard::J)) { render_selected_item_bg = true; bool bottom_reached = select_next_item(true); if(!bottom_reached && on_bottom_reached) on_bottom_reached(); return true; - } else if(rendering_card_view && selected_column > 0 && ((!event.key.control && event.key.code == sf::Keyboard::Left) || (event.key.control && event.key.code == sf::Keyboard::H))) { + } else if(rendering_card_view && selected_column > 0 && ((!event.key.control && event.key.code == mgl::Keyboard::Left) || (event.key.control && event.key.code == mgl::Keyboard::H))) { render_selected_item_bg = true; const int new_selected_item = get_previous_visible_item(selected_item); if(new_selected_item != -1) { @@ -505,7 +498,7 @@ namespace QuickMedia { on_top_reached(); } return true; - } else if(rendering_card_view && selected_column + 1 < num_columns && ((!event.key.control && event.key.code == sf::Keyboard::Right) || (event.key.control && event.key.code == sf::Keyboard::L))) { + } else if(rendering_card_view && selected_column + 1 < num_columns && ((!event.key.control && event.key.code == mgl::Keyboard::Right) || (event.key.control && event.key.code == mgl::Keyboard::L))) { render_selected_item_bg = true; const int new_selected_item = get_next_visible_item(selected_item); if(new_selected_item != -1) { @@ -514,25 +507,25 @@ namespace QuickMedia { on_bottom_reached(); } return true; - } else if(event.key.code == sf::Keyboard::Home) { + } else if(event.key.code == mgl::Keyboard::Home) { render_selected_item_bg = true; select_first_item(false); if(on_top_reached) on_top_reached(); return true; - } else if(event.key.code == sf::Keyboard::End) { + } else if(event.key.code == mgl::Keyboard::End) { render_selected_item_bg = true; select_last_item(); if(on_bottom_reached) on_bottom_reached(); return true; - } else if(event.key.code == sf::Keyboard::PageUp) { + } else if(event.key.code == mgl::Keyboard::PageUp) { render_selected_item_bg = true; bool top_reached = select_previous_page(); if(!top_reached && on_top_reached) on_top_reached(); return true; - } else if(event.key.code == sf::Keyboard::PageDown) { + } else if(event.key.code == mgl::Keyboard::PageDown) { render_selected_item_bg = true; bool bottom_reached = select_next_page(); if(!bottom_reached && on_bottom_reached) @@ -544,11 +537,11 @@ namespace QuickMedia { if(!is_touch_enabled()) return false; - if(event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left && !mouse_left_pressed && sf::FloatRect(body_pos, body_size).contains(sf::Vector2f(event.mouseButton.x, event.mouseButton.y))) { + if(event.type == mgl::Event::MouseButtonPressed && event.mouse_button.button == mgl::Mouse::Left && !mouse_left_pressed && mgl::FloatRect(body_pos, body_size).contains(mgl::vec2f(event.mouse_button.x, event.mouse_button.y))) { mouse_left_pressed = true; - mouse_pos_raw.x = event.mouseButton.x; - mouse_pos_raw.y = event.mouseButton.y; - mouse_pos = sf::Vector2f(mouse_pos_raw.x, mouse_pos_raw.y); + mouse_pos_raw.x = event.mouse_button.x; + mouse_pos_raw.y = event.mouse_button.y; + mouse_pos = mgl::vec2f(mouse_pos_raw.x, mouse_pos_raw.y); prev_mouse_pos_raw = mouse_pos_raw; mouse_click_pos = mouse_pos; mouse_press_pixels_moved_abs = 0.0; @@ -557,20 +550,20 @@ namespace QuickMedia { click_counts = std::abs(mouse_scroll_accel.y) < 5.0f; // Touching the body while it scrolls should stop it, not select the touched item body_swipe_x = 0.0; body_swipe_move_right = false; - grabbed_left_side = (event.mouseButton.x < body_pos.x + body_size.x * 0.15f); + grabbed_left_side = (event.mouse_button.x < body_pos.x + body_size.x * 0.15f); return true; - } else if(event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left && mouse_left_pressed) { + } else if(event.type == mgl::Event::MouseButtonReleased && event.mouse_button.button == mgl::Mouse::Left && mouse_left_pressed) { mouse_left_pressed = false; mouse_left_clicked = true; - mouse_release_pos = sf::Vector2f(event.mouseButton.x, event.mouseButton.y); - if(event.mouseButton.x > body_pos.x + body_size.x * 0.5f || mouse_scroll_accel.x > 20.0f) + mouse_release_pos = mgl::vec2f(event.mouse_button.x, event.mouse_button.y); + if(event.mouse_button.x > body_pos.x + body_size.x * 0.5f || mouse_scroll_accel.x > 20.0f) body_swipe_move_right = true; return true; - } else if(event.type == sf::Event::MouseMoved && mouse_left_pressed) { - sf::Vector2i mouse_pos_diff(event.mouseMove.x - mouse_pos_raw.x, event.mouseMove.y - mouse_pos_raw.y); + } else if(event.type == mgl::Event::MouseMoved && mouse_left_pressed) { + mgl::vec2i mouse_pos_diff(event.mouse_move.x - mouse_pos_raw.x, event.mouse_move.y - mouse_pos_raw.y); mouse_press_pixels_moved_abs += std::sqrt(mouse_pos_diff.x*mouse_pos_diff.x + mouse_pos_diff.y*mouse_pos_diff.y); - mouse_pos_raw.x = event.mouseMove.x; - mouse_pos_raw.y = event.mouseMove.y; + mouse_pos_raw.x = event.mouse_move.x; + mouse_pos_raw.y = event.mouse_move.y; render_selected_item_bg = false; return true; } @@ -578,28 +571,27 @@ namespace QuickMedia { return false; } - void Body::draw_drop_shadow(sf::RenderWindow &window) { + void Body::draw_drop_shadow(mgl::Window &window) { if(!show_drop_shadow) return; - const sf::Color color(0, 0, 0, 50); + const mgl::Color color(0, 0, 0, 50); const float height = 5.0f; - sf::Vertex gradient_points[4]; - gradient_points[0] = sf::Vertex(body_pos + sf::Vector2f(0.0f, 0.0f), color); - gradient_points[1] = sf::Vertex(body_pos + sf::Vector2f(body_size.x, 0.0f), color); - gradient_points[2] = sf::Vertex(body_pos + sf::Vector2f(body_size.x, height), sf::Color(color.r, color.g, color.b, 0)); - gradient_points[3] = sf::Vertex(body_pos + sf::Vector2f(0.0f, height), sf::Color(color.r, color.g, color.b, 0)); - window.draw(gradient_points, 4, sf::Quads); + mgl::Vertex gradient_points[4]; + gradient_points[0] = mgl::Vertex(body_pos + mgl::vec2f(0.0f, 0.0f), color); + gradient_points[1] = mgl::Vertex(body_pos + mgl::vec2f(body_size.x, 0.0f), color); + gradient_points[2] = mgl::Vertex(body_pos + mgl::vec2f(body_size.x, height), mgl::Color(color.r, color.g, color.b, 0)); + gradient_points[3] = mgl::Vertex(body_pos + mgl::vec2f(0.0f, height), mgl::Color(color.r, color.g, color.b, 0)); + window.draw(gradient_points, 4, mgl::PrimitiveType::Quads); } - double Body::draw(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size) { + double Body::draw(mgl::Window &window, mgl::vec2f pos, mgl::vec2f size) { return draw(window, pos, size, Json::Value::nullSingleton()); } // TODO: Use a render target for the whole body so all images can be put into one. - // TODO: Load thumbnails with more than one thread. - double Body::draw(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, const Json::Value &content_progress) { + double Body::draw(mgl::Window &window, mgl::vec2f pos, mgl::vec2f size, const Json::Value &content_progress) { const bool rendering_card_view = card_view && card_view_enabled; body_size_changed = std::abs(size.x - body_size.x) > 0.1f || std::abs(size.y - body_size.y) > 0.1f; @@ -619,7 +611,7 @@ namespace QuickMedia { if(attach_side == AttachSide::TOP) pos.y += body_spacing[body_theme].body_padding_vertical; - float frame_time = frame_timer.restart().asSeconds(); + float frame_time = frame_timer.restart(); if(frame_time > 1.0f) frame_time = 1.0f; @@ -633,7 +625,7 @@ namespace QuickMedia { prev_selected_item = selected_item; } - elapsed_time_sec = draw_timer.getElapsedTime().asSeconds(); + elapsed_time_sec = draw_timer.get_elapsed_time_seconds(); const bool prev_items_cut_off = top_cut_off || bottom_cut_off; const int prev_first_visible_item = first_visible_item; @@ -671,14 +663,14 @@ namespace QuickMedia { } if(is_touch_enabled()) { - const sf::Vector2f mouse_pos_diff(mouse_pos_raw.x - mouse_pos.x, mouse_pos_raw.y - mouse_pos.y); + const mgl::vec2f mouse_pos_diff(mouse_pos_raw.x - mouse_pos.x, mouse_pos_raw.y - mouse_pos.y); const float move_speed = 35.0f; - sf::Vector2f prev_mouse_pos = mouse_pos; + mgl::vec2f prev_mouse_pos = mouse_pos; mouse_pos.x += (mouse_pos_diff.x * std::min(1.0f, frame_time * move_speed)); mouse_pos.y += (mouse_pos_diff.y * std::min(1.0f, frame_time * move_speed)); - const sf::Vector2f mouse_pos_diff_smooth = mouse_pos - prev_mouse_pos; + const mgl::vec2f mouse_pos_diff_smooth = mouse_pos - prev_mouse_pos; - sf::Vector2f mouse_pos_raw_diff(mouse_pos_raw.x - prev_mouse_pos_raw.x, mouse_pos_raw.y - prev_mouse_pos_raw.y); + mgl::vec2f mouse_pos_raw_diff(mouse_pos_raw.x - prev_mouse_pos_raw.x, mouse_pos_raw.y - prev_mouse_pos_raw.y); prev_mouse_pos_raw = mouse_pos_raw; if(prev_items_cut_off) { @@ -687,7 +679,7 @@ namespace QuickMedia { if(body_swipe_x < 0.0) body_swipe_x = 0.0; page_scroll += mouse_pos_diff_smooth.y; - mouse_scroll_accel = sf::Vector2f(mouse_pos_raw_diff.x, mouse_pos_raw_diff.y) / (frame_time * 120.0f); + mouse_scroll_accel = mgl::vec2f(mouse_pos_raw_diff.x, mouse_pos_raw_diff.y) / (frame_time * 120.0f); } else { page_scroll += mouse_scroll_accel.y; } @@ -745,13 +737,12 @@ namespace QuickMedia { selected_scrolled = 0.0f; } - const sf::Vector2u window_size = window.getSize(); - const sf::View prev_view = window.getView(); + const mgl::vec2i window_size = window.get_size(); + const mgl::View prev_view = window.get_view(); if(!rendering_card_view) { - sf::View new_view(sf::FloatRect(0.0f, 0.0f, window_size.x, size.y)); - new_view.setViewport(sf::FloatRect(0.0f, scissor_y / (float)window_size.y, 1.0f, size.y / (float)window_size.y)); - window.setView(new_view); + mgl::View new_view = { mgl::vec2i(0, scissor_y), mgl::vec2i(window_size.x, size.y) }; + window.set_view(new_view); } bool instant_move = body_size_changed; @@ -762,32 +753,34 @@ namespace QuickMedia { const float speed = 30.0f; - const sf::Vector2f item_background_size_diff = sf::Vector2f(item_background_target_size.x, item_background_target_height) - item_background_prev_size; + const mgl::vec2f item_background_size_diff = mgl::vec2f(item_background_target_size.x, item_background_target_height) - item_background_prev_size; const float item_background_size_speed = instant_move ? 1000.0f : speed; - const sf::Vector2f item_background_new_size = item_background_prev_size + (item_background_size_diff * std::min(1.0f, frame_time * item_background_size_speed)); + const mgl::vec2f item_background_new_size = item_background_prev_size + (item_background_size_diff * std::min(1.0f, frame_time * item_background_size_speed)); item_background_prev_size = item_background_new_size; - const sf::Vector2f item_background_pos_diff = item_background_target_pos - item_background_prev_pos; + const mgl::vec2f item_background_pos_diff = item_background_target_pos - item_background_prev_pos; const float item_background_move_speed = instant_move ? 1000.0f : speed; - sf::Vector2f item_background_new_pos = item_background_prev_pos + (item_background_pos_diff * std::min(1.0f, frame_time * item_background_move_speed)); + mgl::vec2f item_background_new_pos = item_background_prev_pos + (item_background_pos_diff * std::min(1.0f, frame_time * item_background_move_speed)); if(selected_item_fits_in_body) { item_background_new_pos.y = std::min(item_background_new_pos.y, size.y - item_background_new_size.y); item_background_new_pos.y = std::max(item_background_new_pos.y, 0.0f); } item_background_prev_pos = item_background_new_pos; + bool switched_to_list_view = false; double body_total_height = 0.0; if(rendering_card_view) { - body_total_height = draw_card_view(window, pos, size, window_size, scissor_y); + body_total_height = draw_card_view(window, pos, size, window_size, scissor_y, switched_to_list_view); } else { body_total_height = draw_list_view(window, pos, size, content_progress); } - window.setView(prev_view); - draw_drop_shadow(window); + window.set_view(prev_view); + if(!switched_to_list_view) + draw_drop_shadow(window); const double scrolling_bar_height_ratio = body_total_height == 0.0 ? 0.0 : (size.y / body_total_height); - if(scrolling_bar_height_ratio <= 1.0) { + if(!switched_to_list_view && scrolling_bar_height_ratio <= 1.0) { const double scrollbar_max_height = size.y - body_spacing[body_theme].body_padding_vertical * 2.0f; double scrollbar_offset_y = body_total_height == 0.0 ? 0.0 : (std::abs(page_scroll) / body_total_height); @@ -808,7 +801,7 @@ namespace QuickMedia { scrollbar_y = std::floor(scissor_y + body_spacing[body_theme].body_padding_vertical + scrollbar_max_height - scrollbar.get_size().y - scrollbar_offset_y * scrollbar_max_height); scrollbar.set_position( - sf::Vector2f(pos.x + scrollbar_offset_x, scrollbar_y)); + mgl::vec2f(pos.x + scrollbar_offset_x, scrollbar_y)); scrollbar.draw(window); } @@ -873,41 +866,37 @@ namespace QuickMedia { void Body::update_dirty_state(BodyItem *body_item, float width) { if((body_item->dirty && !body_item->get_title().empty()) || (body_size_changed && body_item->title_text)) { body_item->dirty = false; - // TODO: Find a way to optimize fromUtf8 - sf::String str = sf::String::fromUtf8(body_item->get_title().begin(), body_item->get_title().end()); if(body_item->title_text) { - body_item->title_text->setString(std::move(str)); + body_item->title_text->setString(body_item->get_title()); body_item->title_text->setMaxWidth(width); } else { - body_item->title_text = std::make_unique(std::move(str), false, std::floor(get_config().body.title_font_size * get_config().scale * get_config().font_scale), width, title_mark_urls); + body_item->title_text = std::make_unique(body_item->get_title(), false, std::floor(get_config().body.title_font_size * get_config().scale * get_config().font_scale), width, title_mark_urls); } - body_item->title_text->setFillColor(body_item->get_title_color()); + body_item->title_text->set_color(body_item->get_title_color()); body_item->title_text->updateGeometry(); } if((body_item->dirty_description && !body_item->get_description().empty()) || (body_size_changed && body_item->description_text)) { body_item->dirty_description = false; - sf::String str = sf::String::fromUtf8(body_item->get_description().begin(), body_item->get_description().end()); if(body_item->description_text) { - body_item->description_text->setString(std::move(str)); + body_item->description_text->setString(body_item->get_description()); body_item->description_text->setMaxWidth(width); } else { - body_item->description_text = std::make_unique(std::move(str), false, std::floor(get_config().body.description_font_size * get_config().scale * get_config().font_scale), width, true); + body_item->description_text = std::make_unique(body_item->get_description(), false, std::floor(get_config().body.description_font_size * get_config().scale * get_config().font_scale), width, true); } - body_item->description_text->setFillColor(body_item->get_description_color()); + body_item->description_text->set_color(body_item->get_description_color()); body_item->description_text->updateGeometry(); } if((body_item->dirty_author && !body_item->get_author().empty()) || (body_size_changed && body_item->author_text)) { body_item->dirty_author = false; - sf::String str = sf::String::fromUtf8(body_item->get_author().begin(), body_item->get_author().end()); if(body_item->author_text) { - body_item->author_text->setString(std::move(str)); + body_item->author_text->setString(body_item->get_author()); body_item->author_text->setMaxWidth(width); } else { - body_item->author_text = std::make_unique(std::move(str), true, std::floor(get_config().body.author_font_size * get_config().scale * get_config().font_scale), width); + body_item->author_text = std::make_unique(body_item->get_author(), true, std::floor(get_config().body.author_font_size * get_config().scale * get_config().font_scale), width); } - body_item->author_text->setFillColor(body_item->get_author_color()); + body_item->author_text->set_color(body_item->get_author_color()); body_item->author_text->updateGeometry(); } @@ -928,12 +917,12 @@ namespace QuickMedia { strftime(time_str, sizeof(time_str) - 1, "%Y %b %d, %a %H:%M", &message_tm); if(body_item->timestamp_text) { - body_item->timestamp_text->setString(time_str); + body_item->timestamp_text->set_string(time_str); } else { - body_item->timestamp_text = std::make_unique(time_str, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(get_config().body.timestamp_font_size * get_config().scale * get_config().font_scale)); + body_item->timestamp_text = std::make_unique(time_str, *FontLoader::get_font(FontLoader::FontType::LATIN, get_config().body.timestamp_font_size * get_config().scale * get_config().font_scale)); } - body_item->timestamp_text->setFillColor(get_theme().timestamp_text_color); + body_item->timestamp_text->set_color(get_theme().timestamp_text_color); } } } @@ -959,13 +948,13 @@ namespace QuickMedia { body_item->keep_alive_frames = 0; } - sf::Vector2i Body::get_item_thumbnail_size(BodyItem *item) const { - sf::Vector2i content_size; - sf::Vector2i thumbnail_max_size_scaled = (card_view && card_view_enabled) ? card_max_image_size : sf::Vector2i(thumbnail_max_size.x * get_config().scale, thumbnail_max_size.y * get_config().scale); + mgl::vec2i Body::get_item_thumbnail_size(BodyItem *item) const { + mgl::vec2i content_size; + mgl::vec2i thumbnail_max_size_scaled = (card_view && card_view_enabled) ? card_max_image_size : mgl::vec2i(thumbnail_max_size.x * get_config().scale, thumbnail_max_size.y * get_config().scale); if(item->thumbnail_size.x > 0 && item->thumbnail_size.y > 0) - content_size = clamp_to_size(sf::Vector2i(std::floor(item->thumbnail_size.x * get_config().scale), std::floor(item->thumbnail_size.y * get_config().scale)), thumbnail_max_size_scaled); + content_size = clamp_to_size(mgl::vec2i(std::floor(item->thumbnail_size.x * get_config().scale), std::floor(item->thumbnail_size.y * get_config().scale)), thumbnail_max_size_scaled); else - content_size = sf::Vector2i(250 * get_config().scale, 141 * get_config().scale); + content_size = mgl::vec2i(250 * get_config().scale, 141 * get_config().scale); return content_size; } @@ -987,7 +976,7 @@ namespace QuickMedia { return -1; } - void Body::draw_item(sf::RenderWindow &window, std::shared_ptr &item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item, bool is_embedded) { + void Body::draw_item(mgl::Window &window, std::shared_ptr &item, mgl::vec2f pos, mgl::vec2f size, bool include_embedded_item, bool is_embedded) { // TODO: What about when |card_view| is used? item->keep_alive_frames = 3; get_item_height(item.get(), size.x, true, false, false, -1); @@ -1010,9 +999,9 @@ namespace QuickMedia { return ""; } - void Body::handle_item_render(const sf::Vector2f pos, const float item_width, const float item_height, int item_index) { + void Body::handle_item_render(const mgl::vec2f pos, const float item_width, const float item_height, int item_index) { if(body_item_select_callback && mouse_left_clicked && !clicked_body_item && click_counts && std::abs(mouse_scroll_accel.y) < 5.0f) { - sf::FloatRect item_box(pos + body_pos, sf::Vector2f(item_width, item_height)); + mgl::FloatRect item_box(pos + body_pos, mgl::vec2f(item_width, item_height)); if(item_box.contains(mouse_click_pos) && item_box.contains(mouse_release_pos) && mouse_press_pixels_moved_abs <= 25.0) { clicked_body_item = items[item_index]; set_selected_item(item_index, false); @@ -1021,7 +1010,7 @@ namespace QuickMedia { if(item_index == selected_item) { item_background_target_pos = pos; - item_background_target_size = sf::Vector2f(item_width, item_height); + item_background_target_size = mgl::vec2f(item_width, item_height); item_background_target_height = item_height; if(target_set == TargetSetState::NOT_SET) target_set = TargetSetState::SET; @@ -1032,11 +1021,11 @@ namespace QuickMedia { return std::min(max, std::max(min, value)); } - static sf::Vector2f round(sf::Vector2f vec) { + static mgl::vec2f round(mgl::vec2f vec) { return { std::floor(vec.x), std::floor(vec.y) }; } - double Body::draw_list_view(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, const Json::Value &content_progress) { + double Body::draw_list_view(mgl::Window &window, mgl::vec2f pos, mgl::vec2f size, const Json::Value &content_progress) { const int num_items = items.size(); const float pos_y_before_scroll = pos.y; @@ -1180,7 +1169,7 @@ namespace QuickMedia { if(selected_item_fits_in_body) { item_background.set_position(round( - sf::Vector2f( + mgl::vec2f( item_background_prev_pos.x, clamp(item_background_prev_pos.y, pos_y_before_scroll, pos_y_before_scroll + size.y - item_background_prev_size.y - body_spacing[body_theme].body_padding_vertical + offset_y_spacing)))); } else { @@ -1202,7 +1191,8 @@ namespace QuickMedia { return std::abs(pos.y - pos_y_start); } - double Body::draw_card_view(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, sf::Vector2u window_size, float scissor_y) { + double Body::draw_card_view(mgl::Window &window, mgl::vec2f pos, mgl::vec2f size, mgl::vec2i window_size, float scissor_y, bool &switched_to_list_view) { + switched_to_list_view = false; num_columns = size.x / card_width; int space_left_column = size.x - (num_columns * card_width); @@ -1223,6 +1213,7 @@ namespace QuickMedia { card_view_enabled = false; const float body_total_height = draw(window, body_pos, body_size); card_view_enabled = true; + switched_to_list_view = true; return body_total_height; } @@ -1238,7 +1229,7 @@ namespace QuickMedia { int row_max_height = 0; const int num_items = items.size(); const float pos_y_start = page_scroll; - sf::Vector2f pos_offset(space_left_column_each, page_scroll); + mgl::vec2f pos_offset(space_left_column_each, page_scroll); while(item_index < num_items) { std::shared_ptr &item = items[item_index]; @@ -1269,7 +1260,7 @@ namespace QuickMedia { if(body_item_render_callback) body_item_render_callback(item); - sf::Vector2i thumbnail_size = get_item_thumbnail_size(item.get()); + mgl::vec2i thumbnail_size = get_item_thumbnail_size(item.get()); std::shared_ptr item_thumbnail; if(draw_thumbnails && !item->thumbnail_url.empty()) item_thumbnail = AsyncImageLoader::get_instance().get_thumbnail(item->thumbnail_url, item->thumbnail_is_local, thumbnail_size); @@ -1288,10 +1279,6 @@ namespace QuickMedia { render_item.item_thumbnail = item_thumbnail; render_items.push_back(std::move(render_item)); - sf::View new_view(sf::FloatRect(0.0f, 0.0f, window_size.x, size.y)); - new_view.setViewport(sf::FloatRect(0.0f, scissor_y / (float)window_size.y, 1.0f, size.y / (float)window_size.y)); - window.setView(new_view); - handle_item_render(pos + pos_offset, card_width, item_height, item_index); ++num_visible_items; @@ -1319,7 +1306,7 @@ namespace QuickMedia { if(drawn_column_index == num_columns) { if(row_has_selected_item) - item_background_target_size = sf::Vector2f(card_width, row_max_height); + item_background_target_size = mgl::vec2f(card_width, row_max_height); drawn_column_index = 0; ++num_visible_rows; @@ -1333,14 +1320,13 @@ namespace QuickMedia { ++item_index; } - sf::View new_view(sf::FloatRect(0.0f, 0.0f, window_size.x, size.y)); - new_view.setViewport(sf::FloatRect(0.0f, scissor_y / (float)window_size.y, 1.0f, size.y / (float)window_size.y)); - window.setView(new_view); + mgl::View new_view = { mgl::vec2i(0, scissor_y), mgl::vec2i(window_size.x, size.y) }; + window.set_view(new_view); for(RenderItem &render_item : render_items) { if(render_item.item_index == selected_item) { item_background.set_position(round( - sf::Vector2f( + mgl::vec2f( item_background_prev_pos.x, clamp(item_background_prev_pos.y, pos.y, pos.y + size.y - item_background_prev_size.y - body_spacing[body_theme].body_padding_vertical - body_spacing[body_theme].spacing_y)))); item_background.set_size(round(item_background_prev_size)); @@ -1351,29 +1337,29 @@ namespace QuickMedia { } for(RenderItem &render_item : render_items) { - draw_card_item(window, render_item.body_item, render_item.pos, render_item.pos_offset, size, sf::Vector2f(window_size.x, window_size.y), render_item.item_height, scissor_y, render_item.item_index, render_item.item_thumbnail.get()); + draw_card_item(window, render_item.body_item, render_item.pos, render_item.pos_offset, size, mgl::vec2f(window_size.x, window_size.y), render_item.item_height, scissor_y, render_item.item_index, render_item.item_thumbnail.get()); } render_items.clear(); if(row_has_selected_item) - item_background_target_size = sf::Vector2f(card_width, row_max_height); + item_background_target_size = mgl::vec2f(card_width, row_max_height); return std::abs(pos_offset.y - pos_y_start); } - void Body::draw_item(sf::RenderWindow &window, std::shared_ptr &item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress, bool include_embedded_item, bool merge_with_previous) { - sf::Vector2i thumbnail_size = get_item_thumbnail_size(item.get()); + void Body::draw_item(mgl::Window &window, std::shared_ptr &item, const mgl::vec2f &pos, const mgl::vec2f &size, const float item_height, const int item_index, const Json::Value &content_progress, bool include_embedded_item, bool merge_with_previous) { + mgl::vec2i thumbnail_size = get_item_thumbnail_size(item.get()); std::shared_ptr item_thumbnail; if(draw_thumbnails && !merge_with_previous && !item->thumbnail_url.empty()) item_thumbnail = AsyncImageLoader::get_instance().get_thumbnail(item->thumbnail_url, item->thumbnail_is_local, thumbnail_size); - thumbnail_size = clamp_to_size_x(thumbnail_size, sf::Vector2i(size.x - body_spacing[body_theme].image_padding_x * 2.0f, thumbnail_size.y)); + thumbnail_size = clamp_to_size_x(thumbnail_size, size.x - body_spacing[body_theme].image_padding_x * 2.0f); if(body_item_render_callback && include_embedded_item) body_item_render_callback(item); - sf::Vector2f item_pos; + mgl::vec2f item_pos; item_pos.x = std::floor(pos.x); item_pos.y = std::floor(pos.y); @@ -1382,51 +1368,52 @@ namespace QuickMedia { float text_offset_x = body_spacing[body_theme].padding_x; if(item_thumbnail && !merge_with_previous) { // TODO: Verify if this is safe. The thumbnail is being modified in another thread - if(item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.getNativeHandle() != 0) { - image.setTexture(item_thumbnail->texture, true); - auto image_size = image.getTexture()->getSize(); - sf::Vector2f image_size_f(image_size.x, image_size.y); - sf::Vector2f content_size = to_vec2f(thumbnail_size); + if(item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.is_valid()) { + image.set_texture(&item_thumbnail->texture); + auto image_size = image.get_texture()->get_size(); + mgl::vec2f image_size_f(image_size.x, image_size.y); + mgl::vec2f content_size = thumbnail_size.to_vec2f(); auto new_image_size = clamp_to_size(image_size_f, content_size); auto image_scale = get_ratio(image_size_f, new_image_size); - image.setScale(image_scale); - image.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y)); + image.set_scale(image_scale); + image.set_position(item_pos + mgl::vec2f(body_spacing[body_theme].image_padding_x, padding_y)); if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) { - thumbnail_mask_shader->setUniform("resolution", new_image_size); + thumbnail_mask_shader->set_uniform("resolution", new_image_size); window.draw(image, thumbnail_mask_shader); } else if(rounded_rectangle_mask_shader) { - rounded_rectangle_mask_shader->setUniform("radius", 10.0f); - rounded_rectangle_mask_shader->setUniform("resolution", new_image_size); + rounded_rectangle_mask_shader->set_uniform("radius", 10.0f); + rounded_rectangle_mask_shader->set_uniform("resolution", new_image_size); window.draw(image, rounded_rectangle_mask_shader); } else { window.draw(image); } text_offset_x += body_spacing[body_theme].image_padding_x + new_image_size.x; // We want the next image fallback to have the same size as the successful image rendering, because its likely the image fallback will have the same size (for example thumbnails on youtube) - //image_fallback.setSize(sf::Vector2f(width_ratio * image_size.x, height_ratio * image_size.y)); + //image_fallback.set_size(mgl::vec2f(width_ratio * image_size.x, height_ratio * image_size.y)); } else if(!item->thumbnail_url.empty()) { - sf::Vector2f content_size = to_vec2f(thumbnail_size); + mgl::vec2f content_size = thumbnail_size.to_vec2f(); if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) { // TODO: Use the mask shader instead, but a vertex shader is also needed for that to pass the vertex coordinates since // shapes dont have texture coordinates. // TODO: Cache circle shape - sf::CircleShape circle_shape(content_size.x * 0.5f); - circle_shape.setFillColor(get_theme().image_loading_background_color); - circle_shape.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y)); - window.draw(circle_shape); + // TODO: Fix + //sf::CircleShape circle_shape(content_size.x * 0.5f); + //circle_shape.set_color(get_theme().image_loading_background_color); + //circle_shape.set_position(item_pos + mgl::vec2f(body_spacing[body_theme].image_padding_x, padding_y)); + //window.draw(circle_shape); } else { - image_fallback.setSize(content_size); - image_fallback.setFillColor(get_theme().image_loading_background_color); - image_fallback.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y)); + image_fallback.set_size(content_size); + image_fallback.set_color(get_theme().image_loading_background_color); + image_fallback.set_position(item_pos + mgl::vec2f(body_spacing[body_theme].image_padding_x, padding_y)); window.draw(image_fallback); } - sf::Vector2f loading_icon_size(loading_icon.getTexture()->getSize().x, loading_icon.getTexture()->getSize().y); + mgl::vec2f loading_icon_size(loading_icon.get_texture()->get_size().x, loading_icon.get_texture()->get_size().y); auto new_loading_icon_size = clamp_to_size(loading_icon_size, content_size); - loading_icon.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y) + (content_size * 0.5f)); - loading_icon.setScale(get_ratio(loading_icon_size, new_loading_icon_size)); - loading_icon.setRotation(elapsed_time_sec * 400.0); + loading_icon.set_position(item_pos + mgl::vec2f(body_spacing[body_theme].image_padding_x, padding_y) + (content_size * 0.5f)); + loading_icon.set_scale(get_ratio(loading_icon_size, new_loading_icon_size)); + loading_icon.set_rotation(elapsed_time_sec * 400.0); window.draw(loading_icon); text_offset_x += body_spacing[body_theme].image_padding_x + item->loaded_image_size.x; } @@ -1436,22 +1423,22 @@ namespace QuickMedia { const float text_offset_y = std::floor(6.0f * get_config().scale * get_config().font_scale); - const float timestamp_text_y = std::floor(item_pos.y + padding_y - text_offset_y); + const float timestamp_text_y = std::floor(item_pos.y + padding_y - text_offset_y - std::floor(4.0f * get_config().scale * get_config().font_scale)); if(item->author_text && !merge_with_previous) { - item->author_text->setPosition(vec2f_floor(item_pos.x + text_offset_x, item_pos.y + padding_y - text_offset_y)); + item->author_text->set_position(vec2f_floor(item_pos.x + text_offset_x, item_pos.y + padding_y - text_offset_y)); item->author_text->draw(window); - sf::Vector2f replies_text_pos = item->author_text->getPosition() + sf::Vector2f(0.0f, 5.0f); + mgl::vec2f replies_text_pos = item->author_text->get_position(); replies_text_pos.x += item->author_text->getWidth() + 5.0f; - replies_text.setPosition(replies_text_pos); + replies_text.set_position(replies_text_pos); - sf::String replies_text_str; + std::string replies_text_str; for(size_t reply_index : item->replies) { BodyItem *reply_item = items[reply_index].get(); replies_text_str += " >>"; replies_text_str += reply_item->post_number; } - replies_text.setString(std::move(replies_text_str)); + replies_text.set_string(std::move(replies_text_str)); window.draw(replies_text); item_pos.y += item->author_text->getHeight() - 2.0f + std::floor(3.0f * get_config().scale); @@ -1460,32 +1447,32 @@ namespace QuickMedia { if(include_embedded_item && item->embedded_item_status != FetchStatus::NONE) { const float embedded_item_width = std::floor(size.x - text_offset_x - embedded_item_border_width - body_spacing[body_theme].padding_x); float embedded_item_height = item->embedded_item ? get_item_height(item->embedded_item.get(), embedded_item_width, true, false) : ((body_spacing[body_theme].embedded_item_font_size + 5.0f) + body_spacing[body_theme].embedded_item_padding_y * 2.0f); - sf::RectangleShape border_left(sf::Vector2f(embedded_item_border_width, std::floor(embedded_item_height))); - border_left.setFillColor(get_theme().embedded_item_border_color); - border_left.setPosition(vec2f_floor(item_pos.x + text_offset_x, item_pos.y + body_spacing[body_theme].embedded_item_padding_y + 2.0f)); + mgl::Rectangle border_left(mgl::vec2f(embedded_item_border_width, std::floor(embedded_item_height))); + border_left.set_color(get_theme().embedded_item_border_color); + border_left.set_position(vec2f_floor(item_pos.x + text_offset_x, item_pos.y + body_spacing[body_theme].embedded_item_padding_y + 2.0f)); window.draw(border_left); if(item->embedded_item) { - sf::Vector2f embedded_item_pos(std::floor(item_pos.x + text_offset_x + embedded_item_border_width + body_spacing[body_theme].padding_x), std::floor(item_pos.y + body_spacing[body_theme].embedded_item_padding_y + 6.0f)); - sf::Vector2f embedded_item_size(embedded_item_width, embedded_item_height); + mgl::vec2f embedded_item_pos(std::floor(item_pos.x + text_offset_x + embedded_item_border_width + body_spacing[body_theme].padding_x), std::floor(item_pos.y + body_spacing[body_theme].embedded_item_padding_y + 6.0f)); + mgl::vec2f embedded_item_size(embedded_item_width, embedded_item_height); draw_item(window, item->embedded_item, embedded_item_pos, embedded_item_size, false, true); } else { - embedded_item_load_text.setString(embedded_item_status_to_string(item->embedded_item_status)); - embedded_item_load_text.setPosition(vec2f_floor(item_pos.x + text_offset_x + embedded_item_border_width + body_spacing[body_theme].padding_x, item_pos.y + embedded_item_height * 0.5f - (body_spacing[body_theme].embedded_item_font_size + 5.0f) * 0.5f + 6.0f)); + embedded_item_load_text.set_string(embedded_item_status_to_string(item->embedded_item_status)); + embedded_item_load_text.set_position(vec2f_floor(item_pos.x + text_offset_x + embedded_item_border_width + body_spacing[body_theme].padding_x, item_pos.y + embedded_item_height * 0.5f - (body_spacing[body_theme].embedded_item_font_size + 5.0f) * 0.5f + 6.0f)); window.draw(embedded_item_load_text); } item_pos.y += embedded_item_height + 4.0f; } if(item->title_text) { - item->title_text->setPosition(vec2f_floor(item_pos.x + text_offset_x, item_pos.y + padding_y - text_offset_y)); + item->title_text->set_position(vec2f_floor(item_pos.x + text_offset_x, item_pos.y + padding_y - text_offset_y)); item->title_text->draw(window); item_pos.y += item->title_text->getHeight() - 2.0f + std::floor(3.0f * get_config().scale); } if(item->description_text) { float height_offset = 0.0f; - item->description_text->setPosition(vec2f_floor(item_pos.x + text_offset_x, item_pos.y + padding_y - text_offset_y + height_offset)); + item->description_text->set_position(vec2f_floor(item_pos.x + text_offset_x, item_pos.y + padding_y - text_offset_y + height_offset)); item->description_text->draw(window); item_pos.y += item->description_text->getHeight() - 2.0f; } @@ -1499,9 +1486,9 @@ namespace QuickMedia { auto &reaction = item->reactions[i]; reaction.text->updateGeometry(); reaction_max_height = std::max(reaction_max_height, reaction.text->getHeight()); - reaction.text->setPosition(vec2f_floor(item_pos.x + text_offset_x + reaction_offset_x + body_spacing[body_theme].reaction_background_padding_x, item_pos.y + padding_y - 4.0f + body_spacing[body_theme].reaction_background_padding_y)); + reaction.text->set_position(vec2f_floor(item_pos.x + text_offset_x + reaction_offset_x + body_spacing[body_theme].reaction_background_padding_x, item_pos.y + padding_y - 4.0f + body_spacing[body_theme].reaction_background_padding_y)); reaction_background.set_position(vec2f_floor(item_pos.x + text_offset_x + reaction_offset_x, item_pos.y + padding_y)); - reaction_background.set_size(sf::Vector2f(reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f, reaction.text->getHeight() + body_spacing[body_theme].reaction_background_padding_y * 2.0f)); + reaction_background.set_size(mgl::vec2f(reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f, reaction.text->getHeight() + body_spacing[body_theme].reaction_background_padding_y * 2.0f)); reaction_background.draw(window); reaction_offset_x += reaction.text->getWidth() + body_spacing[body_theme].reaction_background_padding_x * 2.0f + body_spacing[body_theme].reaction_spacing_x; reaction.text->draw(window); @@ -1515,7 +1502,7 @@ namespace QuickMedia { } if(item_index == selected_item && item->timestamp_text) { - item->timestamp_text->setPosition(vec2f_floor(item_pos.x + size.x - item->timestamp_text->getLocalBounds().width - body_spacing[body_theme].padding_x, timestamp_text_y + 8.0f)); + item->timestamp_text->set_position(vec2f_floor(item_pos.x + size.x - item->timestamp_text->get_bounds().size.x - body_spacing[body_theme].padding_x, timestamp_text_y + 8.0f)); window.draw(*item->timestamp_text); } @@ -1529,126 +1516,124 @@ namespace QuickMedia { const Json::Value ¤t_json = item_progress["current"]; const Json::Value &total_json = item_progress["total"]; if(current_json.isNumeric() && total_json.isNumeric()) { - progress_text.setString(std::string("Page: ") + std::to_string(current_json.asInt()) + "/" + std::to_string(total_json.asInt())); - auto bounds = progress_text.getLocalBounds(); - progress_text.setPosition(vec2f_floor(item_pos.x + size.x - bounds.width - body_spacing[body_theme].padding_x, timestamp_text_y + text_offset_y)); + progress_text.set_string(std::string("Page: ") + std::to_string(current_json.asInt()) + "/" + std::to_string(total_json.asInt())); + auto bounds = progress_text.get_bounds(); + progress_text.set_position(vec2f_floor(item_pos.x + size.x - bounds.size.x - body_spacing[body_theme].padding_x, timestamp_text_y + text_offset_y)); window.draw(progress_text); } } } - void Body::draw_card_item(sf::RenderWindow &window, std::shared_ptr &item, const sf::Vector2f &pos, const sf::Vector2f &pos_offset, const sf::Vector2f &body_size, const sf::Vector2f &window_size, float item_height, float scissor_y, int item_index, ThumbnailData *item_thumbnail) { - const sf::Vector2i thumbnail_size = get_item_thumbnail_size(item.get()); + void Body::draw_card_item(mgl::Window &window, std::shared_ptr &item, const mgl::vec2f &pos, const mgl::vec2f &pos_offset, const mgl::vec2f &body_size, const mgl::vec2f &window_size, float item_height, float scissor_y, int item_index, ThumbnailData *item_thumbnail) { + const mgl::vec2i thumbnail_size = get_item_thumbnail_size(item.get()); - sf::View new_view(sf::FloatRect(0.0f, 0.0f, window_size.x, body_size.y)); - new_view.setViewport(sf::FloatRect(0.0f, scissor_y / (float)window_size.y, 1.0f, body_size.y / (float)window_size.y)); - window.setView(new_view); + mgl::View new_view = { mgl::vec2i(0, scissor_y), mgl::vec2i(window_size.x, body_size.y) }; + window.set_view(new_view); { float image_height = 0.0f; - if(item_thumbnail && item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.getNativeHandle() != 0) { - image.setTexture(item_thumbnail->texture, true); - auto image_size = image.getTexture()->getSize(); - sf::Vector2f image_size_f(image_size.x, image_size.y); - sf::Vector2f content_size = to_vec2f(thumbnail_size); + if(item_thumbnail && item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.is_valid()) { + image.set_texture(&item_thumbnail->texture); + auto image_size = image.get_texture()->get_size(); + mgl::vec2f image_size_f(image_size.x, image_size.y); + mgl::vec2f content_size = thumbnail_size.to_vec2f(); auto new_image_size = clamp_to_size(image_size_f, content_size); auto image_scale = get_ratio(image_size_f, new_image_size); - image.setScale(image_scale); - image.setPosition(pos + pos_offset + sf::Vector2f(card_padding_x, card_padding_y) + sf::Vector2f(card_max_image_size.x * 0.5f, 0.0f) - sf::Vector2f(new_image_size.x * 0.5f, 0.0f)); + image.set_scale(image_scale); + image.set_position(pos + pos_offset + mgl::vec2f(card_padding_x, card_padding_y) + mgl::vec2f(card_max_image_size.x * 0.5f, 0.0f) - mgl::vec2f(new_image_size.x * 0.5f, 0.0f)); image_height = new_image_size.y; if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) { - thumbnail_mask_shader->setUniform("resolution", new_image_size); + thumbnail_mask_shader->set_uniform("resolution", new_image_size); window.draw(image, thumbnail_mask_shader); } else if(rounded_rectangle_mask_shader) { - rounded_rectangle_mask_shader->setUniform("radius", 10.0f); - rounded_rectangle_mask_shader->setUniform("resolution", new_image_size); + rounded_rectangle_mask_shader->set_uniform("radius", 10.0f); + rounded_rectangle_mask_shader->set_uniform("resolution", new_image_size); window.draw(image, rounded_rectangle_mask_shader); } else { window.draw(image); } } else if(!item->thumbnail_url.empty()) { - sf::Vector2f content_size = to_vec2f(thumbnail_size); - sf::Vector2f loading_icon_size(loading_icon.getTexture()->getSize().x, loading_icon.getTexture()->getSize().y); + mgl::vec2f content_size = thumbnail_size.to_vec2f(); + mgl::vec2f loading_icon_size(loading_icon.get_texture()->get_size().x, loading_icon.get_texture()->get_size().y); auto new_loading_icon_size = clamp_to_size(loading_icon_size, content_size); - loading_icon.setPosition(pos + pos_offset + sf::Vector2f(card_padding_x, card_padding_y) + sf::Vector2f(card_max_image_size.x, content_size.y) * 0.5f); - loading_icon.setScale(get_ratio(loading_icon_size, new_loading_icon_size)); - loading_icon.setRotation(elapsed_time_sec * 400.0); + loading_icon.set_position(pos + pos_offset + mgl::vec2f(card_padding_x, card_padding_y) + mgl::vec2f(card_max_image_size.x, content_size.y) * 0.5f); + loading_icon.set_scale(get_ratio(loading_icon_size, new_loading_icon_size)); + loading_icon.set_rotation(elapsed_time_sec * 400.0); window.draw(loading_icon); image_height = content_size.y; } const float text_padding = item_thumbnail ? card_image_text_padding : 0.0f; - sf::Vector2f text_pos = sf::Vector2f(pos.x, scissor_y + body_spacing[body_theme].body_padding_vertical) + pos_offset + sf::Vector2f(card_padding_x, card_padding_y) + sf::Vector2f(0.0f, image_height + text_padding); + mgl::vec2f text_pos = mgl::vec2f(pos.x, scissor_y + body_spacing[body_theme].body_padding_vertical) + pos_offset + mgl::vec2f(card_padding_x, card_padding_y) + mgl::vec2f(0.0f, image_height + text_padding); const float text_height = (item_height - card_padding_y * 2.0f) - image_height - text_padding; const float underflow_text = text_pos.y - scissor_y; const float underflow_height = underflow_text < 0.0f ? std::max(0.0f, text_height + underflow_text) : text_height; - sf::View new_view(sf::FloatRect(0.0f, 0.0f, window_size.x, underflow_height)); - new_view.setViewport(sf::FloatRect(0.0f, std::max(text_pos.y, scissor_y) / (float)window_size.y, 1.0f, underflow_height / (float)window_size.y)); - window.setView(new_view); + + mgl::View new_view = { mgl::vec2i(0, std::max(text_pos.y, scissor_y)), mgl::vec2i(window_size.x, underflow_height) }; + window.set_view(new_view); text_pos.y = std::min(0.0f, underflow_text); float text_offset_y = 0.0f; if(item->author_text) { - item->author_text->setPosition(text_pos); + item->author_text->set_position(text_pos); item->author_text->draw(window); text_offset_y += item->author_text->getHeight(); } if(item->title_text) { - item->title_text->setPosition(text_pos + sf::Vector2f(0.0f, text_offset_y)); + item->title_text->set_position(text_pos + mgl::vec2f(0.0f, text_offset_y)); item->title_text->draw(window); text_offset_y += item->title_text->getHeight(); } if(item->description_text) { - item->description_text->setPosition(text_pos + sf::Vector2f(0.0f, text_offset_y)); + item->description_text->set_position(text_pos + mgl::vec2f(0.0f, text_offset_y)); item->description_text->draw(window); text_offset_y += item->description_text->getHeight(); } const float gradient_height = 5.0f; if(text_offset_y >= text_height - gradient_height && std::abs(item_height - card_height) < 1) { - const sf::Vector2f card_bottom(text_pos.x, text_height); - const sf::Color color = item_index == selected_item ? get_theme().selected_color : get_theme().background_color; - - sf::Vertex gradient_points[4]; - gradient_points[0] = sf::Vertex(card_bottom + sf::Vector2f(0.0f, -gradient_height), sf::Color(color.r, color.g, color.b, 0)); - gradient_points[1] = sf::Vertex(card_bottom + sf::Vector2f(card_max_image_size.x, -gradient_height), sf::Color(color.r, color.g, color.b, 0)); - gradient_points[2] = sf::Vertex(card_bottom + sf::Vector2f(card_max_image_size.x, 0.0f), color); - gradient_points[3] = sf::Vertex(card_bottom + sf::Vector2f(0.0f, 0.0f), color); - window.draw(gradient_points, 4, sf::Quads); + const mgl::vec2f card_bottom(text_pos.x, text_height); + const mgl::Color color = item_index == selected_item ? get_theme().selected_color : get_theme().background_color; + + mgl::Vertex gradient_points[4]; + gradient_points[0] = mgl::Vertex(card_bottom + mgl::vec2f(0.0f, -gradient_height), mgl::Color(color.r, color.g, color.b, 0)); + gradient_points[1] = mgl::Vertex(card_bottom + mgl::vec2f(card_max_image_size.x, -gradient_height), mgl::Color(color.r, color.g, color.b, 0)); + gradient_points[2] = mgl::Vertex(card_bottom + mgl::vec2f(card_max_image_size.x, 0.0f), color); + gradient_points[3] = mgl::Vertex(card_bottom + mgl::vec2f(0.0f, 0.0f), color); + window.draw(gradient_points, 4, mgl::PrimitiveType::Quads); } } } float Body::get_item_height(BodyItem *item, float width, bool load_texture, bool include_embedded_item, bool merge_with_previous, int item_index) { const bool rendering_card_view = card_view && card_view_enabled; - sf::Vector2i content_size = get_item_thumbnail_size(item); + mgl::vec2i content_size = get_item_thumbnail_size(item); const bool show_thumbnail = draw_thumbnails && !item->thumbnail_url.empty() && !merge_with_previous; if(load_texture && show_thumbnail) { std::shared_ptr item_thumbnail = AsyncImageLoader::get_instance().get_thumbnail(item->thumbnail_url, item->thumbnail_is_local, content_size); - content_size = clamp_to_size_x(content_size, sf::Vector2i(width - (rendering_card_view ? 0.0f : body_spacing[body_theme].image_padding_x * 2.0f), content_size.y)); + content_size = clamp_to_size_x(content_size, width - (rendering_card_view ? 0.0f : body_spacing[body_theme].image_padding_x * 2.0f)); - if(item_thumbnail && item_thumbnail->loading_state == LoadingState::FINISHED_LOADING && item_thumbnail->image->getSize().x > 0 && item_thumbnail->image->getSize().y > 0) { - if(!item_thumbnail->texture.loadFromImage(*item_thumbnail->image)) + if(item_thumbnail && item_thumbnail->loading_state == LoadingState::FINISHED_LOADING && item_thumbnail->image->get_size().x > 0 && item_thumbnail->image->get_size().y > 0) { + if(!item_thumbnail->texture.load_from_image(*item_thumbnail->image)) fprintf(stderr, "Warning: failed to load texture from image: %s\n", item->thumbnail_url.c_str()); - item_thumbnail->texture.setSmooth(true); //item_thumbnail->texture.generateMipmap(); item_thumbnail->image.reset(); item_thumbnail->loading_state = LoadingState::APPLIED_TO_TEXTURE; } - if(item_thumbnail && item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.getNativeHandle() != 0) { - auto image_size = item_thumbnail->texture.getSize(); - sf::Vector2f image_size_f(image_size.x, image_size.y); - auto new_image_size = clamp_to_size(image_size_f, to_vec2f(content_size)); + if(item_thumbnail && item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.is_valid()) { + auto image_size = item_thumbnail->texture.get_size(); + mgl::vec2f image_size_f(image_size.x, image_size.y); + auto new_image_size = clamp_to_size(image_size_f, content_size.to_vec2f()); item->loaded_image_size = new_image_size; } else { if(item->loaded_image_size.y < 0.1f) - item->loaded_image_size = to_vec2f(content_size); + item->loaded_image_size = content_size.to_vec2f(); } } else if(item->thumbnail_size.x > 0) { if(!show_thumbnail) diff --git a/src/BodyItem.cpp b/src/BodyItem.cpp index 6523738..ebc3ead 100644 --- a/src/BodyItem.cpp +++ b/src/BodyItem.cpp @@ -45,7 +45,7 @@ namespace QuickMedia { post_number = other.post_number; userdata = other.userdata; loaded_height = 0.0f; - loaded_image_size = sf::Vector2f(0.0f, 0.0f); + loaded_image_size = mgl::vec2f(0.0f, 0.0f); loaded_content_height = 0.0f; embedded_item_status = other.embedded_item_status; if(other.embedded_item) { @@ -77,14 +77,13 @@ namespace QuickMedia { } void BodyItem::add_reaction(std::string text, void *userdata) { - sf::String str = sf::String::fromUtf8(text.begin(), text.end()); Reaction reaction; - reaction.text = std::make_unique(std::move(str), false, std::floor(get_config().body.reaction_font_size * get_config().scale * get_config().font_scale), 0.0f); + reaction.text = std::make_unique(std::move(text), false, std::floor(get_config().body.reaction_font_size * get_config().scale * get_config().font_scale), 0.0f); reaction.userdata = userdata; reactions.push_back(std::move(reaction)); } - void BodyItem::draw_list(Body *body, sf::RenderTarget &render_target) { + void BodyItem::draw_list(Body *body, mgl::Window &render_target) { } } \ No newline at end of file diff --git a/src/DownloadUtils.cpp b/src/DownloadUtils.cpp index 6df9c74..584d4a3 100644 --- a/src/DownloadUtils.cpp +++ b/src/DownloadUtils.cpp @@ -5,8 +5,8 @@ #include "../external/hash-library/sha256.h" #include #include -#include -#include +#include +#include #include #include @@ -86,7 +86,7 @@ namespace QuickMedia { DownloadResult download_head_to_string(const std::string &url, std::string &result, bool use_browser_useragent, bool fail_on_error) { result.clear(); - sf::Clock timer; + mgl::Clock timer; std::vector args; args.insert(args.end(), { "curl", "-I", "-g", "-H", "Accept-Language: en-US,en;q=0.5", "-H", "Connection: keep-alive", "--compressed", "-s" }); if(fail_on_error) @@ -107,13 +107,13 @@ namespace QuickMedia { } if(exec_program(args.data(), accumulate_string, &result) != 0) return DownloadResult::NET_ERR; - fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), timer.getElapsedTime().asMilliseconds()); + fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), (int)(timer.get_elapsed_time_seconds() * 1000.0)); return DownloadResult::OK; } DownloadResult url_get_remote_name(const std::string &url, std::string &result, bool use_browser_useragent) { result.clear(); - sf::Clock timer; + mgl::Clock timer; std::vector args; args.insert(args.end(), { "curl", "-I", "-g", "-H", "Accept-Language: en-US,en;q=0.5", "-H", "Connection: keep-alive", "--compressed", "-s" }); if(use_browser_useragent) { @@ -133,7 +133,7 @@ namespace QuickMedia { std::string header; if(exec_program(args.data(), accumulate_string, &header) != 0) return DownloadResult::NET_ERR; - fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), timer.getElapsedTime().asMilliseconds()); + fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), (int)(timer.get_elapsed_time_seconds() * 1000.0)); std::string content_disposition = header_extract_value(header, "content-disposition"); // TODO: after filename*= the encoding type will follow. We need to support other formats than utf-8 as well @@ -195,7 +195,7 @@ namespace QuickMedia { // TODO: Add timeout DownloadResult download_to_string(const std::string &url, std::string &result, const std::vector &additional_args, bool use_browser_useragent, bool fail_on_error, bool cloudflare_bypass, std::vector *headers, int download_limit) { result.clear(); - sf::Clock timer; + mgl::Clock timer; std::vector args; args.insert(args.end(), { "curl", "-H", "Accept-Language: en-US,en;q=0.5", "-H", "Connection: keep-alive", "--compressed", "-g", "-s", "-L" }); if(fail_on_error) @@ -234,7 +234,7 @@ namespace QuickMedia { if(exec_program(args.data(), accumulate_string_with_header, &download_userdata) != 0) return DownloadResult::NET_ERR; - fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), timer.getElapsedTime().asMilliseconds()); + fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), (int)(timer.get_elapsed_time_seconds() * 1000.0)); return DownloadResult::OK; } @@ -307,7 +307,7 @@ namespace QuickMedia { // TODO: Add timeout DownloadResult download_to_json(const std::string &url, rapidjson::Document &result, const std::vector &additional_args, bool use_browser_useragent, bool fail_on_error) { - sf::Clock timer; + mgl::Clock timer; std::vector args; args.insert(args.end(), { "curl", "-H", "Accept-Language: en-US,en;q=0.5", "-H", "Connection: keep-alive", "--compressed", "-g", "-s", "-L" }); if(fail_on_error) @@ -350,7 +350,7 @@ namespace QuickMedia { fclose(file); wait_program(read_program.pid); - fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), timer.getElapsedTime().asMilliseconds()); + fprintf(stderr, "Download duration for %s: %d ms\n", url.c_str(), (int)(timer.get_elapsed_time_seconds() * 1000.0)); return parse_result.IsError() ? DownloadResult::ERR : DownloadResult::OK; } } diff --git a/src/Downloader.cpp b/src/Downloader.cpp index 820ca81..1bb3e34 100644 --- a/src/Downloader.cpp +++ b/src/Downloader.cpp @@ -2,7 +2,7 @@ #include "../include/Storage.hpp" #include "../include/NetUtils.hpp" #include "../include/Notification.hpp" -#include +#include #include #include @@ -346,8 +346,8 @@ namespace QuickMedia { } downloader_task = AsyncTask([this]() { - sf::Clock timer; - const double sleep_time_millisec = 1; + mgl::Clock timer; + // TODO: Poll instead of sleep while(!program_is_dead_in_current_thread()) { if(youtube_video_media_proxy) youtube_video_media_proxy->update(); @@ -355,9 +355,9 @@ namespace QuickMedia { if(youtube_audio_media_proxy) youtube_audio_media_proxy->update(); - const int sleep_time = sleep_time_millisec - timer.restart().asMilliseconds(); - if(sleep_time > 0) - std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time)); + const double sleep_left_sec = timer.restart(); + if(sleep_left_sec > 0.000001) + std::this_thread::sleep_for(std::chrono::milliseconds((long)(sleep_left_sec * 1000.0))); } }); diff --git a/src/Entry.cpp b/src/Entry.cpp index f0c02fd..590eade 100644 --- a/src/Entry.cpp +++ b/src/Entry.cpp @@ -3,9 +3,10 @@ #include "../include/Config.hpp" #include "../include/Utils.hpp" #include "../include/Theme.hpp" -#include -#include -#include +#include +#include +#include +#include #include namespace QuickMedia { @@ -13,29 +14,29 @@ namespace QuickMedia { static const float padding_vertical = std::floor(5.0f * get_config().scale); static const float background_margin_vertical = std::floor(0.0f * get_config().scale); - Entry::Entry(const std::string &placeholder_text, sf::Shader *rounded_rectangle_shader) : + Entry::Entry(const std::string &placeholder_text, mgl::Shader *rounded_rectangle_shader) : on_submit_callback(nullptr), draw_background(true), text("", false, std::floor(get_config().input.font_size * get_config().scale * get_config().font_scale), 0.0f), width(0.0f), - background(sf::Vector2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().selected_color, rounded_rectangle_shader), - placeholder(placeholder_text, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(get_config().input.font_size * get_config().scale * get_config().font_scale)), + background(mgl::vec2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().selected_color, rounded_rectangle_shader), + placeholder(placeholder_text, *FontLoader::get_font(FontLoader::FontType::LATIN, get_config().input.font_size * get_config().scale * get_config().font_scale)), mouse_left_inside(false) { text.setEditable(true); - placeholder.setFillColor(get_theme().placeholder_text_color); + placeholder.set_color(get_theme().placeholder_text_color); } - void Entry::process_event(sf::Event &event) { - if(is_touch_enabled() && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) { - sf::FloatRect box(background.get_position(), background.get_size()); - if(box.contains(event.mouseButton.x, event.mouseButton.y)) + void Entry::process_event(mgl::Window &window, mgl::Event &event) { + if(is_touch_enabled() && event.type == mgl::Event::MouseButtonPressed && event.mouse_button.button == mgl::Mouse::Left) { + mgl::FloatRect box(background.get_position(), background.get_size()); + if(box.contains(mgl::vec2f(event.mouse_button.x, event.mouse_button.y))) mouse_left_inside = true; else mouse_left_inside = false; - } else if(is_touch_enabled() && event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left) { - sf::FloatRect box(background.get_position(), background.get_size()); - if(mouse_left_inside && box.contains(event.mouseButton.x, event.mouseButton.y)) + } else if(is_touch_enabled() && event.type == mgl::Event::MouseButtonReleased && event.mouse_button.button == mgl::Mouse::Left) { + mgl::FloatRect box(background.get_position(), background.get_size()); + if(mouse_left_inside && box.contains(mgl::vec2f(event.mouse_button.x, event.mouse_button.y))) show_virtual_keyboard(); mouse_left_inside = false; } @@ -43,13 +44,11 @@ namespace QuickMedia { if(!text.isEditable()) return; - text.processEvent(event); + text.processEvent(window, event); - if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Enter && !event.key.shift) { + if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Enter && !event.key.shift) { if(on_submit_callback) { - auto u8 = text.getString().toUtf8(); - std::string *u8_str = (std::string*)&u8; - bool clear_text = on_submit_callback(*u8_str); + bool clear_text = on_submit_callback(text.getString()); if(clear_text) text.setString(""); } @@ -58,18 +57,18 @@ namespace QuickMedia { // TODO: Set the max number of visible lines and use glScissor to cut off the lines outsides // (and also split text into lines to not draw them at all once they are not inside the scissor box) - void Entry::draw(sf::RenderWindow &window) { - background.set_size(sf::Vector2f(width, get_height())); + void Entry::draw(mgl::Window &window) { + background.set_size(mgl::vec2f(width, get_height())); if(draw_background) background.draw(window); - if(text.getString().isEmpty() && !text.isEditable()) { + if(text.getString().empty() && !text.isEditable()) { window.draw(placeholder); - //sf::Vector2f placeholder_pos = placeholder.getPosition(); + //mgl::vec2f placeholder_pos = placeholder.get_position(); //const float caret_margin = 2.0f; //const float vspace = placeholder.getFont()->getLineSpacing(18); - //sf::RectangleShape caret_rect(sf::Vector2f(2.0f, floor(vspace - caret_margin * 2.0f))); - //caret_rect.setPosition(floor(placeholder_pos.x), floor(placeholder_pos.y + caret_margin)); + //mgl::Rectangle caret_rect(mgl::vec2f(2.0f, floor(vspace - caret_margin * 2.0f))); + //caret_rect.set_position(floor(placeholder_pos.x), floor(placeholder_pos.y + caret_margin)); //window.draw(caret_rect); } else { text.draw(window); @@ -84,8 +83,8 @@ namespace QuickMedia { text.setEditable(editable); } - void Entry::set_text(const std::string &new_text) { - text.setString(sf::String::fromUtf8(new_text.begin(), new_text.end())); + void Entry::set_text(std::string new_text) { + text.setString(std::move(new_text)); } void Entry::move_caret_to_end() { @@ -93,11 +92,11 @@ namespace QuickMedia { text.moveCaretToEnd(); } - void Entry::append_text(const std::string &str) { - text.appendText(sf::String::fromUtf8(str.begin(), str.end())); + void Entry::insert_text_at_caret_position(const std::string &str) { + text.insert_text_at_caret_position(str); } - void Entry::replace(size_t start_index, size_t length, const sf::String &insert_str) { + void Entry::replace(size_t start_index, size_t length, const std::string &insert_str) { text.replace(start_index, length, insert_str); } @@ -105,10 +104,10 @@ namespace QuickMedia { return text.getCaretIndex(); } - void Entry::set_position(const sf::Vector2f &pos) { + void Entry::set_position(const mgl::vec2f &pos) { background.set_position(pos); - text.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical)); - placeholder.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical + std::floor(5.0f * get_config().scale))); + text.set_position(pos + mgl::vec2f(background_margin_horizontal, background_margin_vertical)); + placeholder.set_position(pos + mgl::vec2f(background_margin_horizontal, background_margin_vertical + std::floor(-1.0f * get_config().scale))); } void Entry::set_max_width(float width) { @@ -125,7 +124,7 @@ namespace QuickMedia { return std::floor(text.getHeight() + background_margin_vertical * 2.0f + padding_vertical * 2.0f); } - const sf::String& Entry::get_text() const { + const std::string& Entry::get_text() const { return text.getString(); } } \ No newline at end of file diff --git a/src/FileAnalyzer.cpp b/src/FileAnalyzer.cpp index f1f9369..6f1c1ee 100644 --- a/src/FileAnalyzer.cpp +++ b/src/FileAnalyzer.cpp @@ -137,7 +137,7 @@ namespace QuickMedia { if(width > 0 && height > 0) { FileAnalyzer file_analyzer; - const bool success = file_analyzer.load_file(destination_path_tmp.data.c_str(), false) && create_thumbnail(destination_path_tmp, destination_path, sf::Vector2i(width, height), file_analyzer.get_content_type(), false); + const bool success = file_analyzer.load_file(destination_path_tmp.data.c_str(), false) && create_thumbnail(destination_path_tmp, destination_path, mgl::vec2i(width, height), file_analyzer.get_content_type(), false); remove(destination_path_tmp.data.c_str()); return success; } else { diff --git a/src/ImageViewer.cpp b/src/ImageViewer.cpp index 9c6abf7..731099f 100644 --- a/src/ImageViewer.cpp +++ b/src/ImageViewer.cpp @@ -1,34 +1,37 @@ #include "../include/ImageViewer.hpp" #include "../include/Notification.hpp" #include "../include/Storage.hpp" -#include "../include/SfmlFixes.hpp" #include "../include/ResourceLoader.hpp" #include "../include/Scale.hpp" #include "../include/Config.hpp" +#include #include #include -#include -#include -#include +#include +#include +#include +#include namespace QuickMedia { - static sf::Vector2 get_no_image_size_scaled(sf::Vector2 window_size, bool fit_image_to_window) { - sf::Vector2 no_image_page_size(720.0, 1280.0); - sf::Vector2f no_image_page_size_f(no_image_page_size.x, no_image_page_size.y); - sf::Vector2f content_size(window_size.x, window_size.y); + static const int page_text_character_size = 14 * get_config().scale * get_config().font_scale; - sf::Vector2f image_scale; + static mgl::vec2d get_no_image_size_scaled(mgl::vec2d window_size, bool fit_image_to_window) { + mgl::vec2d no_image_page_size(720.0, 1280.0); + mgl::vec2f no_image_page_size_f(no_image_page_size.x, no_image_page_size.y); + mgl::vec2f content_size(window_size.x, window_size.y); + + mgl::vec2f image_scale; if(fit_image_to_window) - image_scale = get_ratio(no_image_page_size_f, wrap_to_size_x(no_image_page_size_f, content_size)); + image_scale = get_ratio(no_image_page_size_f, wrap_to_size_x(no_image_page_size_f, content_size.x)); else - image_scale = get_ratio(no_image_page_size_f, clamp_to_size_x(no_image_page_size_f, content_size)); + image_scale = get_ratio(no_image_page_size_f, clamp_to_size_x(no_image_page_size_f, content_size.x)); no_image_page_size.x *= image_scale.x; no_image_page_size.y *= image_scale.y; return no_image_page_size; } - ImageViewer::ImageViewer(sf::RenderWindow *window, int num_pages, const std::string &content_title, const std::string &chapter_title, int current_page, const Path &chapter_cache_dir, bool *fit_image_to_window) : + ImageViewer::ImageViewer(mgl::Window *window, int num_pages, const std::string &content_title, const std::string &chapter_title, int current_page, const Path &chapter_cache_dir, bool *fit_image_to_window) : window(window), current_page(current_page), num_pages(num_pages), @@ -36,8 +39,7 @@ namespace QuickMedia { chapter_title(chapter_title), chapter_cache_dir(chapter_cache_dir), focused_page(current_page), - font(FontLoader::get_font(FontLoader::FontType::LATIN)), - page_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), 14 * get_config().scale * get_config().font_scale), + page_text("", *FontLoader::get_font(FontLoader::FontType::LATIN, page_text_character_size)), fit_image_to_window(fit_image_to_window) { current_page = std::min(current_page, num_pages); @@ -47,29 +49,30 @@ namespace QuickMedia { image_data[i] = nullptr; page_size[i].loaded = false; } - page_text.setFillColor(sf::Color::White); + page_text.set_color(mgl::Color(255, 255, 255, 255)); - has_default_cursor = default_cursor.loadFromSystem(sf::Cursor::Arrow); - has_size_vertical_cursor = size_vertical_cursor.loadFromSystem(sf::Cursor::SizeVertical); + // TODO: Fix + //has_default_cursor = default_cursor.loadFromSystem(sf::Cursor::Arrow); + //has_size_vertical_cursor = size_vertical_cursor.loadFromSystem(sf::Cursor::SizeVertical); } ImageViewer::~ImageViewer() { - if(has_default_cursor) - window->setMouseCursor(default_cursor); + // TODO: Fix + //if(has_default_cursor) + // window->setMouseCursor(default_cursor); if(image_loader_thread.joinable()) image_loader_thread.join(); } void ImageViewer::load_image_async(const Path &path, std::shared_ptr image_data) { image_data->image_status = ImageStatus::LOADING; - //image_data->texture.setSmooth(true); assert(!loading_image); loading_image = true; if(image_loader_thread.joinable()) image_loader_thread.join(); image_loader_thread = std::thread([this, image_data, path]() mutable { - auto image = std::make_unique(); - if(load_image_from_file(*image, path.data)) { + auto image = std::make_unique(); + if(image->load_from_file(path.data.c_str())) { image_data->image = std::move(image); image_data->image_status = ImageStatus::LOADED; } else { @@ -79,13 +82,13 @@ namespace QuickMedia { }); } - bool ImageViewer::render_page(sf::RenderWindow &window, int page, double offset_y) { + bool ImageViewer::render_page(mgl::Window &window, int page, double offset_y) { if(page < 0 || page >= (int)image_data.size()) return false; std::shared_ptr &page_image_data = image_data[page]; - const sf::Vector2 image_size = get_page_size(page); - sf::Vector2 render_pos(std::floor(window_size.x * 0.5 - image_size.x * 0.5), scroll + offset_y); + const mgl::vec2d image_size = get_page_size(page); + mgl::vec2d render_pos(std::floor(window_size.x * 0.5 - image_size.x * 0.5), scroll + offset_y); if(render_pos.y + image_size.y <= 0.0 || render_pos.y >= window_size.y) { if(page_image_data) page_image_data->visible_on_screen = false; @@ -106,18 +109,18 @@ namespace QuickMedia { page_image_data->visible_on_screen = true; if(page_image_data->image_status == ImageStatus::APPLIED_TO_TEXTURE) { - auto texture_size = page_image_data->sprite.getTexture()->getSize(); - sf::Vector2f texture_size_f(texture_size.x, texture_size.y); - sf::Vector2f content_size(window_size.x, window_size.y); + auto texture_size = page_image_data->sprite.get_texture()->get_size(); + mgl::vec2f texture_size_f(texture_size.x, texture_size.y); + mgl::vec2f content_size(window_size.x, window_size.y); - sf::Vector2f image_scale; + mgl::vec2f image_scale; if(*fit_image_to_window) - image_scale = get_ratio(texture_size_f, wrap_to_size_x(texture_size_f, content_size)); + image_scale = get_ratio(texture_size_f, wrap_to_size_x(texture_size_f, content_size.x)); else - image_scale = get_ratio(texture_size_f, clamp_to_size_x(texture_size_f, content_size)); + image_scale = get_ratio(texture_size_f, clamp_to_size_x(texture_size_f, content_size.x)); - page_image_data->sprite.setScale(image_scale); - page_image_data->sprite.setPosition(render_pos.x, render_pos.y); + page_image_data->sprite.set_scale(image_scale); + page_image_data->sprite.set_position(mgl::vec2f(render_pos.x, render_pos.y)); window.draw(page_image_data->sprite); } else { std::string page_str = std::to_string(1 + page); @@ -135,39 +138,39 @@ namespace QuickMedia { msg = "Failed to load image for page " + page_str; } - sf::Text error_message(std::move(msg), *font, 30 * get_config().scale * get_config().font_scale); - auto text_bounds = error_message.getLocalBounds(); - error_message.setFillColor(sf::Color::Black); - sf::Vector2 render_pos_text(std::floor(window_size.x * 0.5 - text_bounds.width * 0.5), image_size.y * 0.5 - text_bounds.height * 0.5 + scroll + offset_y); + mgl::Text error_message(std::move(msg), *FontLoader::get_font(FontLoader::FontType::LATIN, 30 * get_config().scale * get_config().font_scale)); + auto text_bounds = error_message.get_bounds(); + error_message.set_color(mgl::Color(0, 0, 0, 255)); + mgl::vec2d render_pos_text(std::floor(window_size.x * 0.5 - text_bounds.size.x * 0.5), image_size.y * 0.5 - text_bounds.size.y * 0.5 + scroll + offset_y); if(!scrolling) render_pos_text.y = std::floor(render_pos_text.y); - sf::RectangleShape background(sf::Vector2f(image_size.x, image_size.y)); - background.setFillColor(sf::Color::White); - background.setPosition(render_pos.x, render_pos.y); + mgl::Rectangle background(mgl::vec2f(image_size.x, image_size.y)); + background.set_color(mgl::Color(255, 255, 255, 255)); + background.set_position(mgl::vec2f(render_pos.x, render_pos.y)); window.draw(background); - error_message.setPosition(render_pos_text.x, render_pos_text.y); + error_message.set_position(mgl::vec2f(render_pos_text.x, render_pos_text.y)); window.draw(error_message); } } else { std::string page_str = std::to_string(1 + page); - sf::Text error_message("Downloading page " + page_str, *font, 30 * get_config().scale * get_config().font_scale); - auto text_bounds = error_message.getLocalBounds(); - error_message.setFillColor(sf::Color::Black); - sf::Vector2 render_pos_text(std::floor(window_size.x * 0.5 - text_bounds.width * 0.5), image_size.y * 0.5 - text_bounds.height * 0.5 + scroll + offset_y); + mgl::Text error_message("Downloading page " + page_str, *FontLoader::get_font(FontLoader::FontType::LATIN, 30 * get_config().scale * get_config().font_scale)); + auto text_bounds = error_message.get_bounds(); + error_message.set_color(mgl::Color(0, 0, 0, 255)); + mgl::vec2d render_pos_text(std::floor(window_size.x * 0.5 - text_bounds.size.x * 0.5), image_size.y * 0.5 - text_bounds.size.y * 0.5 + scroll + offset_y); if(!scrolling) render_pos_text.y = std::floor(render_pos_text.y); - sf::RectangleShape background(sf::Vector2f(image_size.x, image_size.y)); - background.setFillColor(sf::Color::White); - background.setPosition(render_pos.x, render_pos.y); + mgl::Rectangle background(mgl::vec2f(image_size.x, image_size.y)); + background.set_color(mgl::Color(255, 255, 255, 255)); + background.set_position(mgl::vec2f(render_pos.x, render_pos.y)); window.draw(background); - error_message.setPosition(render_pos_text.x, render_pos_text.y); + error_message.set_position(mgl::vec2f(render_pos_text.x, render_pos_text.y)); window.draw(error_message); Path image_path = chapter_cache_dir; @@ -181,7 +184,6 @@ namespace QuickMedia { page_image_data->visible_on_screen = true; page_image_data->image_status = ImageStatus::WAITING; - //page_image_data->texture.setSmooth(true); } } @@ -193,73 +195,69 @@ namespace QuickMedia { } ImageViewerAction ImageViewer::draw() { - const double frame_delta = frame_timer.restart().asSeconds(); + const double frame_delta = frame_timer.restart(); const double scroll_speed_key_input = 50.0; const double scroll_speed_mouse_wheel = 600.0; const double scroll_speed_autoscroll = 10.0; const double scroll_deaccel = 0.96; if(!window_size_set) { - auto window_size_i = window->getSize(); + auto window_size_i = window->get_size(); window_size.x = window_size_i.x; window_size.y = window_size_i.y; window_size_set = true; for(int i = 0; i < current_page; ++i) { - const sf::Vector2 size = get_page_size(i); + const mgl::vec2d size = get_page_size(i); scroll -= size.y; page_size[i].prev_size = size; } } // TODO: Only redraw when scrolling and when image has finished downloading - sf::Event event; - while(window->pollEvent(event)) { - if(event.type == sf::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::Q && event.key.control) + mgl::Event event; + while(window->poll_event(event)) { + if(event.type == mgl::Event::KeyPressed) { + if(event.key.code == mgl::Keyboard::Q && event.key.control) window->close(); } - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window->setView(sf::View(visible_area)); - //redraw = true; - } else if(event.type == sf::Event::GainedFocus) { - //redraw = true; - } else if(event.type == sf::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::Up || (event.key.control && event.key.code == sf::Keyboard::K)) + } else if(event.type == mgl::Event::KeyPressed) { + if(event.key.code == mgl::Keyboard::Up || (event.key.control && event.key.code == mgl::Keyboard::K)) up_pressed = true; - if(event.key.code == sf::Keyboard::Down || (event.key.control && event.key.code == sf::Keyboard::J)) + if(event.key.code == mgl::Keyboard::Down || (event.key.control && event.key.code == mgl::Keyboard::J)) down_pressed = true; - if(event.key.code == sf::Keyboard::Escape) + if(event.key.code == mgl::Keyboard::Escape) return ImageViewerAction::RETURN; - if(event.key.code == sf::Keyboard::I) + if(event.key.code == mgl::Keyboard::I) return ImageViewerAction::SWITCH_TO_SINGLE_IMAGE_MODE; - if(event.key.code == sf::Keyboard::F) + if(event.key.code == mgl::Keyboard::F) *fit_image_to_window = !*fit_image_to_window; - } else if(event.type == sf::Event::KeyReleased) { - if(event.key.code == sf::Keyboard::Up || (event.key.control && event.key.code == sf::Keyboard::K)) + } else if(event.type == mgl::Event::KeyReleased) { + if(event.key.code == mgl::Keyboard::Up || (event.key.control && event.key.code == mgl::Keyboard::K)) up_pressed = false; - if(event.key.code == sf::Keyboard::Down || (event.key.control && event.key.code == sf::Keyboard::J)) + if(event.key.code == mgl::Keyboard::Down || (event.key.control && event.key.code == mgl::Keyboard::J)) down_pressed = false; - } else if(event.type == sf::Event::MouseWheelScrolled && event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel) { - scroll_speed += scroll_speed_mouse_wheel * event.mouseWheelScroll.delta * frame_delta; - } else if(event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Button::Middle) { + } else if(event.type == mgl::Event::MouseWheelScrolled/* && event.mouse_wheel_scroll.wheel == mgl::Mouse::VerticalWheel*/) { + scroll_speed += scroll_speed_mouse_wheel * event.mouse_wheel_scroll.delta * frame_delta; + } else if(event.type == mgl::Event::MouseButtonPressed && event.mouse_button.button == mgl::Mouse::Button::Middle) { middle_mouse_scrolling = true; - autoscroll_start_y = sf::Mouse::getPosition(*window).y; - if(has_size_vertical_cursor) - window->setMouseCursor(size_vertical_cursor); - - } else if(event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Button::Middle) { + autoscroll_start_y = window->get_mouse_position().y; + // TODO: Fix + //if(has_size_vertical_cursor) + // window->setMouseCursor(size_vertical_cursor); + } else if(event.type == mgl::Event::MouseButtonReleased && event.mouse_button.button == mgl::Mouse::Button::Middle) { middle_mouse_scrolling = false; scroll_speed = 0.0; - if(has_default_cursor) - window->setMouseCursor(default_cursor); + // TODO: Fix + //if(has_default_cursor) + // window->setMouseCursor(default_cursor); } } @@ -269,7 +267,7 @@ namespace QuickMedia { scroll_speed -= scroll_speed_key_input * frame_delta; if(middle_mouse_scrolling) { - double distance_to_start_y = (double)sf::Mouse::getPosition(*window).y - autoscroll_start_y; + double distance_to_start_y = (double)window->get_mouse_position().y - autoscroll_start_y; double dist_abs = std::abs(distance_to_start_y); dist_abs -= 20.0; if(dist_abs < 0.0) @@ -304,14 +302,13 @@ namespace QuickMedia { int page_i = 0; for(auto &page_data : image_data) { if(page_data) { - if(page_data->image_status == ImageStatus::LOADED && page_data->image->getSize().x > 0 && page_data->image->getSize().y > 0) { - if(page_data->texture.loadFromImage(*page_data->image)) { - page_data->texture.setSmooth(true); + if(page_data->image_status == ImageStatus::LOADED && page_data->image->get_size().x > 0 && page_data->image->get_size().y > 0) { + if(page_data->texture.load_from_image(*page_data->image)) { //page_data->texture.generateMipmap(); page_data->image_status = ImageStatus::APPLIED_TO_TEXTURE; - page_data->sprite.setTexture(page_data->texture, true); - sf::Vector2u texture_size = image_data[page_i]->texture.getSize(); - page_size[page_i].size = sf::Vector2(texture_size.x, texture_size.y); + page_data->sprite.set_texture(&page_data->texture); + mgl::vec2i texture_size = image_data[page_i]->texture.get_size(); + page_size[page_i].size = mgl::vec2d(texture_size.x, texture_size.y); page_size[page_i].loaded = true; } else { page_data->image_status = ImageStatus::FAILED_TO_LOAD; @@ -326,7 +323,7 @@ namespace QuickMedia { double page_offset = 0.0; for(int i = 0; i < num_pages; ++i) { - const sf::Vector2 current_page_size = get_page_size(i); + const mgl::vec2d current_page_size = get_page_size(i); const double scroll_diff = current_page_size.y - page_size[i].prev_size.y; page_size[i].prev_size = current_page_size; @@ -349,19 +346,19 @@ namespace QuickMedia { if(focused_page != prev_focused_page) { prev_focused_page = focused_page; - page_text.setString(content_title + " | " + chapter_title + " | Page " + std::to_string(1 + focused_page) + "/" + std::to_string(num_pages)); + page_text.set_string(content_title + " | " + chapter_title + " | Page " + std::to_string(1 + focused_page) + "/" + std::to_string(num_pages)); } - const float font_height = page_text.getCharacterSize() + 8.0f; + const float font_height = page_text_character_size + 8.0f; const float background_height = font_height + 6.0f; - sf::RectangleShape page_text_background(sf::Vector2f(window_size.x, background_height)); - page_text_background.setFillColor(sf::Color(0, 0, 0, 150)); - page_text_background.setPosition(0.0f, window_size.y - background_height); + mgl::Rectangle page_text_background(mgl::vec2f(window_size.x, background_height)); + page_text_background.set_color(mgl::Color(0, 0, 0, 150)); + page_text_background.set_position(mgl::vec2f(0.0f, window_size.y - background_height)); window->draw(page_text_background); - auto page_text_bounds = page_text.getLocalBounds(); - page_text.setPosition(std::floor(window_size.x * 0.5f - page_text_bounds.width * 0.5f), std::floor(window_size.y - background_height * 0.5f - font_height * 0.5f)); + auto page_text_bounds = page_text.get_bounds(); + page_text.set_position(mgl::vec2f(std::floor(window_size.x * 0.5f - page_text_bounds.size.x * 0.5f), std::floor(window_size.y - background_height * 0.5f - font_height * 0.6f))); window->draw(page_text); // Free pages that are not visible on the screen @@ -385,30 +382,30 @@ namespace QuickMedia { return 1 + focused_page; } - sf::Vector2 ImageViewer::get_page_size(int page) { - sf::Vector2 no_image_page_size = get_no_image_size_scaled(window_size, *fit_image_to_window); + mgl::vec2d ImageViewer::get_page_size(int page) { + mgl::vec2d no_image_page_size = get_no_image_size_scaled(window_size, *fit_image_to_window); if(page < 0 || page >= (int)image_data.size()) return no_image_page_size; if(page_size[page].loaded) { - sf::Vector2f texture_size_f(page_size[page].size.x, page_size[page].size.y); - sf::Vector2f content_size(window_size.x, window_size.y); + mgl::vec2f texture_size_f(page_size[page].size.x, page_size[page].size.y); + mgl::vec2f content_size(window_size.x, window_size.y); - sf::Vector2f image_scale; + mgl::vec2f image_scale; if(*fit_image_to_window) - image_scale = get_ratio(texture_size_f, wrap_to_size_x(texture_size_f, content_size)); + image_scale = get_ratio(texture_size_f, wrap_to_size_x(texture_size_f, content_size.x)); else - image_scale = get_ratio(texture_size_f, clamp_to_size_x(texture_size_f, content_size)); + image_scale = get_ratio(texture_size_f, clamp_to_size_x(texture_size_f, content_size.x)); - return sf::Vector2(page_size[page].size.x * image_scale.x, page_size[page].size.y * image_scale.y); + return mgl::vec2d(page_size[page].size.x * image_scale.x, page_size[page].size.y * image_scale.y); } if(!image_data[page] || image_data[page]->image_status != ImageStatus::APPLIED_TO_TEXTURE) return no_image_page_size; // Do not scale here, because this will be used to set page_size[page].size - sf::Vector2u texture_size = image_data[page]->texture.getSize(); - return sf::Vector2(texture_size.x, texture_size.y); + mgl::vec2i texture_size = image_data[page]->texture.get_size(); + return mgl::vec2d(texture_size.x, texture_size.y); } } \ No newline at end of file diff --git a/src/NetUtils.cpp b/src/NetUtils.cpp index 4f5fce8..2dab2b8 100644 --- a/src/NetUtils.cpp +++ b/src/NetUtils.cpp @@ -273,51 +273,6 @@ namespace QuickMedia { return strings; } - static size_t is_start_of_utf8_codepoint(uint8_t c) { - if((c & 0x80) == 0) - return true; - else if((c & 0xE0) == 0xC0) - return true; - else if((c & 0xF0) == 0xE0) - return true; - else if((c & 0xF8) == 0xF0) - return true; - else - return false; - } - - void convert_utf8_to_utf32_ranges(const std::string &str, std::vector &ranges) { - if(ranges.empty()) - return; - - size_t ranges_index = 0; - size_t prev_range_offset = 0; - size_t num_codepoints = 0; - bool in_range = false; - - for(size_t i = 0; i < str.size(); ++i) { - if(ranges_index > 0 && in_range) { - ++prev_range_offset; - if(prev_range_offset == ranges[ranges_index - 1].length) { - ranges[ranges_index - 1].length = num_codepoints - ranges[ranges_index - 1].start; - prev_range_offset = 0; - in_range = false; - } - } - - if(i == ranges[ranges_index].start) { - in_range = true; - ranges[ranges_index].start = num_codepoints; - ++ranges_index; - if(ranges_index == ranges.size()) - break; - } - - if(is_start_of_utf8_codepoint(*(uint8_t*)&str[i])) - ++num_codepoints; - } - } - std::string header_extract_value(const std::string &header, const std::string &type) { std::string result; string_split(header, '\n', [&type, &result](const char *str, size_t size) { diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 69252fa..1a7f67a 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -29,7 +29,6 @@ #include "../external/cppcodec/base64_url.hpp" #include "../include/Entry.hpp" #include "../include/NetUtils.hpp" -#include "../include/SfmlFixes.hpp" #include "../include/ResourceLoader.hpp" #include "../include/Config.hpp" #include "../include/Tabs.hpp" @@ -38,6 +37,7 @@ #include "../include/Downloader.hpp" #include "../include/Storage.hpp" #include "../include/AsyncImageLoader.hpp" +#include #include "../plugins/youtube/YoutubeMediaProxy.hpp" #include "../include/gui/Button.hpp" #include "../external/hash-library/sha256.h" @@ -51,19 +51,22 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +extern "C" { +#include +} #include #include #include #include +#include static int FPS_IDLE; static const double IDLE_TIMEOUT_SEC = 2.0; -static const sf::Vector2i AVATAR_THUMBNAIL_SIZE(std::floor(32), std::floor(32)); +static const mgl::vec2i AVATAR_THUMBNAIL_SIZE(std::floor(32), std::floor(32)); static const float more_items_height = 2.0f; static const std::pair valid_plugins[] = { @@ -181,12 +184,12 @@ static void get_screen_resolution(Display *display, int *width, int *height) { *height = DefaultScreenOfDisplay(display)->height; } -static sf::Color interpolate_colors(sf::Color source, sf::Color target, double progress) { +static mgl::Color interpolate_colors(mgl::Color source, mgl::Color target, double progress) { int diff_r = (int)target.r - (int)source.r; int diff_g = (int)target.g - (int)source.g; int diff_b = (int)target.b - (int)source.b; int diff_a = (int)target.a - (int)source.a; - return sf::Color( + return mgl::Color( source.r + diff_r * progress, source.g + diff_g * progress, source.b + diff_b * progress, @@ -505,6 +508,7 @@ namespace QuickMedia { }; no_video = force_no_video; + mgl_init(); init(parent_window, program_path); if(strcmp(plugin_name, "download") == 0) { @@ -555,20 +559,31 @@ namespace QuickMedia { return exit_code; } - static sf::Vector2i get_focused_monitor_center(Display *disp, sf::Vector2i &monitor_size) { + // TODO: Move to mgl + static mgl::vec2i get_global_mouse_position(Display *display) { + Window dummy_w; + int dummy_i; + unsigned int dummy_u; + + mgl::vec2i mouse_pos; + XQueryPointer(display, DefaultRootWindow(display), &dummy_w, &dummy_w, &mouse_pos.x, &mouse_pos.y, &dummy_i, &dummy_i, &dummy_u); + return mouse_pos; + } + + static mgl::vec2i get_focused_monitor_center(Display *disp, mgl::vec2i &monitor_size) { int screen = DefaultScreen(disp); monitor_size.x = DisplayWidth(disp, screen); monitor_size.y = DisplayWidth(disp, screen); int screen_center_x = monitor_size.x / 2; int screen_center_y = monitor_size.y / 2; - sf::Vector2i focused_monitor_center(screen_center_x, screen_center_y); - auto mouse_pos = sf::Mouse::getPosition(); + mgl::vec2i focused_monitor_center(screen_center_x, screen_center_y); + mgl::vec2i mouse_pos = get_global_mouse_position(disp); for_each_active_monitor_output(disp, [&focused_monitor_center, mouse_pos, &monitor_size](const XRRCrtcInfo *crtc_info, const XRRModeInfo*){ - if(sf::Rect(crtc_info->x, crtc_info->y, crtc_info->width, crtc_info->height).contains(mouse_pos)) { + if(mgl::Rect(mgl::vec2i(crtc_info->x, crtc_info->y), mgl::vec2i(crtc_info->width, crtc_info->height)).contains(mouse_pos)) { monitor_size.x = crtc_info->width; monitor_size.y = crtc_info->height; - focused_monitor_center = sf::Vector2i(crtc_info->x + crtc_info->width/2, crtc_info->y + crtc_info->height/2); + focused_monitor_center = mgl::vec2i(crtc_info->x + crtc_info->width/2, crtc_info->y + crtc_info->height/2); } }); @@ -585,51 +600,26 @@ namespace QuickMedia { XSetErrorHandler(x_error_handler); XSetIOErrorHandler(x_io_error_handler); - wm_delete_window_atom = XInternAtom(disp, "WM_DELETE_WINDOW", False); - net_wm_ping_atom = XInternAtom(disp, "_NET_WM_PING", True); - - int screen = DefaultScreen(disp); - sf::Vector2i monitor_size; - sf::Vector2i focused_monitor_center = get_focused_monitor_center(disp, monitor_size); + mgl::vec2i monitor_size; + mgl::vec2i focused_monitor_center = get_focused_monitor_center(disp, monitor_size); if(strcmp(plugin_name, "download") == 0) { window_size.x = std::min(900, monitor_size.x); window_size.y = std::min(900, monitor_size.y); } - x11_window = XCreateWindow(disp, parent_window ? parent_window : DefaultRootWindow(disp), - focused_monitor_center.x - window_size.x * 0.5f, focused_monitor_center.y - window_size.y * 0.5f, window_size.x, window_size.y, 0, - DefaultDepth(disp, screen), - InputOutput, - DefaultVisual(disp, screen), - 0, nullptr); - if(!x11_window) { - show_notification("QuickMedia", "Failed to create window", Urgency::CRITICAL); - abort(); - } - + mgl::Window::CreateParams window_create_params; + window_create_params.position = { focused_monitor_center.x - window_size.x / 2, focused_monitor_center.y - window_size.y / 2 }; + window_create_params.size = window_size; if(strcmp(plugin_name, "download") == 0) { - XSizeHints *size_hints = XAllocSizeHints(); - if(size_hints) { - size_hints->width = window_size.x; - size_hints->min_width = window_size.x; - size_hints->max_width = window_size.x; - - size_hints->height = window_size.y; - size_hints->min_height = window_size.y; - size_hints->max_height = window_size.y; - size_hints->flags = PSize | PMinSize | PMaxSize; - - XSetWMNormalHints(disp, x11_window, size_hints); - XFree(size_hints); - } + window_create_params.min_size = window_size; + window_create_params.max_size = window_size; + } + window_create_params.parent_window = parent_window; + if(!window.create("QuickMedia", std::move(window_create_params))) { + show_notification("QuickMedia", "Failed to create opengl window", Urgency::CRITICAL); + abort(); } - - XStoreName(disp, x11_window, "QuickMedia"); - XMapWindow(disp, x11_window); - XFlush(disp); - - window.create(x11_window); if(!program_path.empty() && program_path.back() != '/') program_path += '/'; @@ -641,39 +631,39 @@ namespace QuickMedia { set_resource_loader_root_path(resources_root.c_str()); set_use_system_fonts(get_config().use_system_fonts); + init_body_themes(); if(!is_touch_enabled()) { - if(!circle_mask_shader.loadFromFile(resources_root + "shaders/circle_mask.glsl", sf::Shader::Type::Fragment)) { + if(!circle_mask_shader.load_from_file((resources_root + "shaders/circle_mask.glsl").c_str(), mgl::Shader::Type::Fragment)) { show_notification("QuickMedia", "Failed to load " + resources_root + "/shaders/circle_mask.glsl", Urgency::CRITICAL); abort(); } if(get_theme().drop_shadow) { - if(!rounded_rectangle_shader.loadFromFile(resources_root + "shaders/rounded_rectangle.glsl", sf::Shader::Type::Fragment)) { + if(!rounded_rectangle_shader.load_from_file((resources_root + "shaders/rounded_rectangle.glsl").c_str(), mgl::Shader::Type::Fragment)) { show_notification("QuickMedia", "Failed to load " + resources_root + "/shaders/rounded_rectangle.glsl", Urgency::CRITICAL); abort(); } } else { - if(!rounded_rectangle_shader.loadFromFile(resources_root + "shaders/rounded_rectangle_no_shadow.glsl", sf::Shader::Type::Fragment)) { + if(!rounded_rectangle_shader.load_from_file((resources_root + "shaders/rounded_rectangle_no_shadow.glsl").c_str(), mgl::Shader::Type::Fragment)) { show_notification("QuickMedia", "Failed to load " + resources_root + "/shaders/rounded_rectangle_no_shadow.glsl", Urgency::CRITICAL); abort(); } } - if(!rounded_rectangle_mask_shader.loadFromFile(resources_root + "shaders/rounded_rectangle_mask.glsl", sf::Shader::Type::Fragment)) { + if(!rounded_rectangle_mask_shader.load_from_file((resources_root + "shaders/rounded_rectangle_mask.glsl").c_str(), mgl::Shader::Type::Fragment)) { show_notification("QuickMedia", "Failed to load " + resources_root + "/shaders/rounded_rectangle_mask.glsl", Urgency::CRITICAL); abort(); } } - if(!loading_icon.loadFromFile(resources_root + "images/loading_icon.png")) { + if(!loading_icon.load_from_file((resources_root + "images/loading_icon.png").c_str())) { show_notification("QuickMedia", "Failed to load " + resources_root + "/images/loading_icon.png", Urgency::CRITICAL); abort(); } - loading_icon.setSmooth(true); - load_sprite.setTexture(loading_icon, true); - sf::Vector2u loading_icon_size = loading_icon.getSize(); - load_sprite.setOrigin(loading_icon_size.x * 0.5f, loading_icon_size.y * 0.5f); + load_sprite.set_texture(&loading_icon); + mgl::vec2i loading_icon_size = loading_icon.get_size(); + load_sprite.set_origin(mgl::vec2f(loading_icon_size.x * 0.5f, loading_icon_size.y * 0.5f)); struct sigaction action; action.sa_handler = sigpipe_handler; @@ -684,9 +674,8 @@ namespace QuickMedia { XSetErrorHandler(x_error_handler); XSetIOErrorHandler(x_io_error_handler); - window.setVerticalSyncEnabled(true); monitor_hz = get_monitor_max_hz(disp); - window.setFramerateLimit(monitor_hz); + window.set_framerate_limit(monitor_hz); idle = false; fprintf(stderr, "Monitor hz: %d\n", monitor_hz); @@ -717,7 +706,7 @@ namespace QuickMedia { show_room_side_panel = true; main_thread_id = std::this_thread::get_id(); - auto window_size_u = window.getSize(); + auto window_size_u = window.get_size(); window_size.x = window_size_u.x; window_size.y = window_size_u.y; } @@ -1038,7 +1027,7 @@ namespace QuickMedia { if(!plugin_name || plugin_name[0] == '\0') return; - window.setTitle("QuickMedia - " + std::string(plugin_name)); + window.set_title(("QuickMedia - " + std::string(plugin_name)).c_str()); no_video = force_no_video; if(strcmp(plugin_name, "youtube-audio") == 0) { @@ -1051,12 +1040,12 @@ namespace QuickMedia { if(plugin_logo_name) plugin_logo_path = resources_root + "images/" + plugin_logo_name; - plugin_logo = sf::Texture(); + plugin_logo = mgl::Texture(); if(!plugin_logo_path.empty()) { - if(!plugin_logo.loadFromFile(plugin_logo_path)) + if(!plugin_logo.load_from_file(plugin_logo_path.c_str())) fprintf(stderr, "Failed to load plugin logo, path: %s\n", plugin_logo_path.c_str()); - plugin_logo.generateMipmap(); - plugin_logo.setSmooth(true); + // TODO: Fix + //plugin_logo.generateMipmap(); } if(strcmp(plugin_name, "launcher") == 0) { @@ -1253,13 +1242,13 @@ namespace QuickMedia { } } else if(strcmp(plugin_name, "pornhub") == 0) { check_youtube_dl_installed(plugin_name); - auto search_page = std::make_unique(this, "https://www.pornhub.com/", sf::Vector2i(320/1.5f, 180/1.5f), false); + auto search_page = std::make_unique(this, "https://www.pornhub.com/", mgl::vec2i(320/1.5f, 180/1.5f), false); add_pornhub_handlers(search_page.get()); tabs.push_back(Tab{create_body(false, true), std::move(search_page), create_search_bar("Search...", 500)}); use_youtube_dl = true; } else if(strcmp(plugin_name, "spankbang") == 0) { check_youtube_dl_installed(plugin_name); - auto search_page = std::make_unique(this, "https://spankbang.com/", sf::Vector2i(500/2.5f, 281/2.5f), true); + auto search_page = std::make_unique(this, "https://spankbang.com/", mgl::vec2i(500/2.5f, 281/2.5f), true); add_spankbang_handlers(search_page.get()); tabs.push_back(Tab{create_body(false, true), std::move(search_page), create_search_bar("Search...", 500)}); use_youtube_dl = true; @@ -1269,13 +1258,13 @@ namespace QuickMedia { std::vector extra_commands = { { "-H", "Cookie: last_views=%5B%2236247565-" + std::to_string(time(nullptr)) + "%22%5D" } }; - auto search_page = std::make_unique(this, "https://www.xvideos.com/", sf::Vector2i(352/1.5f, 198/1.5f), false, std::move(extra_commands)); + auto search_page = std::make_unique(this, "https://www.xvideos.com/", mgl::vec2i(352/1.5f, 198/1.5f), false, std::move(extra_commands)); add_xvideos_handlers(search_page.get()); tabs.push_back(Tab{create_body(false, true), std::move(search_page), create_search_bar("Search...", 500)}); use_youtube_dl = true; } else if(strcmp(plugin_name, "xhamster") == 0) { check_youtube_dl_installed(plugin_name); - auto search_page = std::make_unique(this, "https://xhamster.com/", sf::Vector2i(240, 135), false); + auto search_page = std::make_unique(this, "https://xhamster.com/", mgl::vec2i(240, 135), false); add_xhamster_handlers(search_page.get()); tabs.push_back(Tab{create_body(false, true), std::move(search_page), create_search_bar("Search...", 500)}); use_youtube_dl = true; @@ -1296,53 +1285,44 @@ namespace QuickMedia { } } - void Program::common_event_handler(sf::Event &event) { - if(event.type == sf::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::Q && event.key.control) + void Program::common_event_handler(mgl::Event &event) { + if(event.type == mgl::Event::KeyPressed) { + if(event.key.code == mgl::Keyboard::Q && event.key.control) window.close(); } } void Program::handle_x11_events() { - window_closed = false; - - while(XCheckTypedWindowEvent(disp, x11_window, ClientMessage, &xev)) { - if(net_wm_ping_atom && xev.xclient.format == 32 && (Atom)xev.xclient.data.l[0] == net_wm_ping_atom) { - fprintf(stderr, "Responding to X11 ping\n"); - xev.xclient.window = DefaultRootWindow(disp); - XSendEvent(disp, DefaultRootWindow(disp), False, SubstructureNotifyMask | SubstructureRedirectMask, &xev); - } else if(wm_delete_window_atom && xev.xclient.format == 32 && (Atom)xev.xclient.data.l[0] == wm_delete_window_atom) { - current_page = PageType::EXIT; - window.close(); - window_closed = true; - } + if(window.is_open()) { + window_closed = false; + } else { + window_closed = true; + current_page = PageType::EXIT; } } - void Program::base_event_handler(sf::Event &event, PageType previous_page, Body *body, SearchBar *search_bar, bool handle_keypress, bool handle_searchbar) { - if(event.type == sf::Event::Resized) { + void Program::base_event_handler(mgl::Event &event, PageType previous_page, Body *body, SearchBar *search_bar, bool handle_keypress, bool handle_searchbar) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); - } else if(handle_keypress && event.type == sf::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::Escape) { + } else if(handle_keypress && event.type == mgl::Event::KeyPressed) { + if(event.key.code == mgl::Keyboard::Escape) { current_page = previous_page; } } else if(handle_searchbar) { assert(search_bar); - search_bar->on_event(event); + search_bar->on_event(window, event); } } - void Program::event_idle_handler(const sf::Event &event) { - if(event.type == sf::Event::KeyPressed || event.type == sf::Event::TextEntered) + void Program::event_idle_handler(const mgl::Event &event) { + if(event.type == mgl::Event::KeyPressed || event.type == mgl::Event::TextEntered) idle_active_handler(); } void Program::idle_active_handler() { if(idle) - window.setFramerateLimit(monitor_hz); + window.set_framerate_limit(monitor_hz); idle = false; idle_timer.restart(); } @@ -1351,8 +1331,8 @@ namespace QuickMedia { if(idle) return; - if(idle_timer.getElapsedTime().asSeconds() > IDLE_TIMEOUT_SEC) { - window.setFramerateLimit(FPS_IDLE); + if(idle_timer.get_elapsed_time_seconds() > IDLE_TIMEOUT_SEC) { + window.set_framerate_limit(FPS_IDLE); idle = true; } } @@ -1391,7 +1371,7 @@ namespace QuickMedia { body_item->thumbnail_url = "https://img.youtube.com/vi/" + video_id_str + "/mqdefault.jpg"; body_item->set_description("Watched " + seconds_to_relative_time_str(time_now - timestamp.asInt64())); body_item->set_description_color(get_theme().faded_text_color); - body_item->thumbnail_size = sf::Vector2i(192, 108); + body_item->thumbnail_size = mgl::vec2i(192, 108); history_items.push_back(std::move(body_item)); } @@ -1428,6 +1408,10 @@ namespace QuickMedia { return json_result; } + void Program::set_clipboard(const std::string &str) { + window.set_clipboard(str); + } + void Program::manga_get_watch_history(const char *plugin_name, BodyItems &history_items) { // TOOD: Make generic, instead of checking for plugin Path content_storage_dir = get_storage_dir().join(plugin_name); @@ -1492,7 +1476,7 @@ namespace QuickMedia { fill_history_items_from_json(load_video_history_json(), history_items); } - static void get_body_dimensions(const sf::Vector2f &window_size, SearchBar *search_bar, sf::Vector2f &body_pos, sf::Vector2f &body_size, bool has_tabs = false) { + static void get_body_dimensions(const mgl::vec2i &window_size, SearchBar *search_bar, mgl::vec2f &body_pos, mgl::vec2f &body_size, bool has_tabs = false) { const float body_width = window_size.x; float tab_h = Tabs::get_shade_height(); @@ -1503,12 +1487,12 @@ namespace QuickMedia { tab_h = 0.0f; float search_bottom = search_bar ? search_bar->getBottomWithoutShadow() : 0.0f; - body_pos = sf::Vector2f(0.0f, search_bottom + tab_h); - body_size = sf::Vector2f(body_width, window_size.y - search_bottom - tab_h); + body_pos = mgl::vec2f(0.0f, search_bottom + tab_h); + body_size = mgl::vec2f(body_width, window_size.y - search_bottom - tab_h); } std::unique_ptr Program::create_body(bool plain_text_list, bool prefer_card_view) { - if(rounded_rectangle_mask_shader.getNativeHandle() == 0) + if(!rounded_rectangle_mask_shader.is_valid()) plain_text_list = true; auto body = std::make_unique(plain_text_list ? BODY_THEME_MINIMAL : BODY_THEME_MODERN_SPACIOUS, loading_icon, &rounded_rectangle_shader, &rounded_rectangle_mask_shader); body->card_view = prefer_card_view; @@ -1518,7 +1502,7 @@ namespace QuickMedia { std::unique_ptr Program::create_search_bar(const std::string &placeholder, int search_delay) { auto search_bar = std::make_unique(&plugin_logo, &rounded_rectangle_shader, placeholder); - search_bar->text_autosearch_delay = search_delay; + search_bar->text_autosearch_delay_ms = search_delay; return search_bar; } @@ -1556,7 +1540,7 @@ namespace QuickMedia { } bool Program::is_window_focused() { - return window.hasFocus(); + return window.has_focus(); } RoomData* Program::get_current_chat_room() { @@ -1686,38 +1670,38 @@ namespace QuickMedia { return true; } - void Program::page_loop_render(sf::RenderWindow &window, std::vector &tabs, int selected_tab, TabAssociatedData &tab_associated_data, const Json::Value *json_chapters, Tabs &ui_tabs) { - if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->draw(window, window_size, true); + void Program::page_loop_render(mgl::Window &window, std::vector &tabs, int selected_tab, TabAssociatedData &tab_associated_data, const Json::Value *json_chapters, Tabs &ui_tabs) { + if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->draw(window, window_size.to_vec2f(), true); float shade_extra_height = 0.0f; if(!tabs[selected_tab].search_bar) { shade_extra_height = std::floor(10.0f * get_config().scale); - sf::RectangleShape shade_top(sf::Vector2f(window_size.x, shade_extra_height)); - shade_top.setFillColor(get_theme().shade_color); + mgl::Rectangle shade_top(mgl::vec2f(window_size.x, shade_extra_height)); + shade_top.set_color(get_theme().shade_color); window.draw(shade_top); } float tab_vertical_offset = tabs[selected_tab].search_bar ? tabs[selected_tab].search_bar->getBottomWithoutShadow() : 0.0f; - ui_tabs.draw(window, sf::Vector2f(0.0f, tab_vertical_offset + shade_extra_height), window_size.x); + ui_tabs.draw(window, mgl::vec2f(0.0f, tab_vertical_offset + shade_extra_height), window_size.x); tabs[selected_tab].body->draw(window, body_pos, body_size, *json_chapters); if(tab_associated_data.fetching_next_page_running) - window.draw(gradient_points, 4, sf::Quads); // TODO: sf::Quads doesn't work with egl + window.draw(gradient_points, 4, mgl::PrimitiveType::Quads); // TODO: mgl::PrimitiveType::Quads doesn't work with egl - if(!tab_associated_data.search_result_text.getString().isEmpty() && !tabs[selected_tab].page->search_is_suggestion()) { - auto search_result_text_bounds = tab_associated_data.search_result_text.getLocalBounds(); - tab_associated_data.search_result_text.setPosition( - std::floor(body_pos.x + body_size.x * 0.5f - search_result_text_bounds.width * 0.5f), - std::floor(body_pos.y + body_size.y * 0.5f - search_result_text_bounds.height * 0.5f)); + if(!tab_associated_data.search_result_text.get_string().empty() && !tabs[selected_tab].page->search_is_suggestion()) { + auto search_result_text_bounds = tab_associated_data.search_result_text.get_bounds(); + tab_associated_data.search_result_text.set_position(mgl::vec2f( + std::floor(body_pos.x + body_size.x * 0.5f - search_result_text_bounds.size.x * 0.5f), + std::floor(body_pos.y + body_size.y * 0.5f - search_result_text_bounds.size.y * 0.5f))); window.draw(tab_associated_data.search_result_text); } if(!tabs[selected_tab].page->is_ready()) { - sf::Text loading_text("Loading...", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(30 * get_config().scale * get_config().font_scale)); - auto text_bounds = loading_text.getLocalBounds(); - loading_text.setPosition( - std::floor(body_pos.x + body_size.x * 0.5f - text_bounds.width * 0.5f), - std::floor(body_pos.y + body_size.y * 0.5f - text_bounds.height * 0.5f)); + mgl::Text loading_text("Loading...", *FontLoader::get_font(FontLoader::FontType::LATIN, 30 * get_config().scale * get_config().font_scale)); + auto text_bounds = loading_text.get_bounds(); + loading_text.set_position(mgl::vec2f( + std::floor(body_pos.x + body_size.x * 0.5f - text_bounds.size.x * 0.5f), + std::floor(body_pos.y + body_size.y * 0.5f - text_bounds.size.y * 0.5f))); window.draw(loading_text); } @@ -1726,8 +1710,8 @@ namespace QuickMedia { if(matrix && !matrix->is_initial_sync_finished()) { // if(is_login_sync) { - load_sprite.setPosition(body_pos.x + body_size.x * 0.5f, body_pos.y + body_size.y * 0.5f); - load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0); + load_sprite.set_position(mgl::vec2f(body_pos.x + body_size.x * 0.5f, body_pos.y + body_size.y * 0.5f)); + load_sprite.set_rotation(load_sprite_timer.get_elapsed_time_seconds() * 400.0); window.draw(load_sprite); // } std::string err_msg; @@ -1796,28 +1780,28 @@ namespace QuickMedia { std::vector tab_associated_data; for(size_t i = 0; i < tabs.size(); ++i) { TabAssociatedData data; - data.search_result_text = sf::Text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(30 * get_config().scale * get_config().font_scale)); + data.search_result_text = mgl::Text("", *FontLoader::get_font(FontLoader::FontType::LATIN, 30 * get_config().scale * get_config().font_scale)); tab_associated_data.push_back(std::move(data)); } double gradient_inc = 0.0; const float gradient_height = 5.0f; - auto window_size_u = window.getSize(); + auto window_size_u = window.get_size(); window_size.x = window_size_u.x; window_size.y = window_size_u.y; std::function submit_handler = [this, &submit_handler, &after_submit_handler, &tabs, &tab_associated_data, &ui_tabs, &loop_running, &redraw](const std::string &search_text) { - sf::Event event; - while(window.pollEvent(event)) { common_event_handler(event); } + mgl::Event event; + while(window.poll_event(event)) { common_event_handler(event); } const int selected_tab = ui_tabs.get_selected(); auto selected_item = tabs[selected_tab].body->get_selected_shared(); if(!selected_item && search_text.empty()) return; - if(tabs[selected_tab].page->allow_submit_no_selection() && (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))) - selected_item = nullptr; + if(tabs[selected_tab].page->allow_submit_no_selection() && (window.is_key_pressed(mgl::Keyboard::LControl) || window.is_key_pressed(mgl::Keyboard::RControl))) + selected_item = nullptr; if(!selected_item && !tabs[selected_tab].page->allow_submit_no_selection()) return; @@ -1925,7 +1909,7 @@ namespace QuickMedia { tabs[selected_tab].search_bar->clear(); chapters_body->filter_search_fuzzy(""); // Needed (or not really) to go to the next chapter when reaching the last page of a chapter MangaImagesPage *manga_images_page = static_cast(new_tabs[0].page.get()); - window.setKeyRepeatEnabled(false); + window.set_key_repeat_enabled(false); downloading_chapter_url.clear(); Path manga_progress_dir = get_storage_dir().join(manga_images_page->get_service_name()); @@ -1933,7 +1917,7 @@ namespace QuickMedia { show_notification("QuickMedia", "Failed to create directory: " + manga_progress_dir.data, Urgency::CRITICAL); current_page = pop_page_stack(); } else { - while(window.isOpen() && (current_page == PageType::IMAGES || current_page == PageType::IMAGES_CONTINUOUS)) { + while(window.is_open() && (current_page == PageType::IMAGES || current_page == PageType::IMAGES_CONTINUOUS)) { if(current_page == PageType::IMAGES) { while(current_page == PageType::IMAGES) { int page_navigation = image_page(manga_images_page, chapters_body); @@ -1963,7 +1947,7 @@ namespace QuickMedia { image_download_cancel = false; images_to_upscale_queue.clear(); num_manga_pages = 0; - window.setKeyRepeatEnabled(true); + window.set_key_repeat_enabled(true); malloc_trim(0); } else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::IMAGE_BOARD_THREAD) { page_stack.push(current_page); @@ -1986,7 +1970,7 @@ namespace QuickMedia { current_chat_room = matrix->get_room_by_id(tmp_matrix_chat_page->room_id); rooms_page->body->show_drop_shadow = false; - while(window.isOpen() && current_chat_room) { + while(window.is_open() && current_chat_room) { auto matrix_chat_page = std::make_unique(this, current_chat_room->id, rooms_page, jump_to_event_id); bool move_room = chat_page(matrix_chat_page.get(), current_chat_room); matrix_chat_page->messages_tab_visible = false; @@ -2037,7 +2021,7 @@ namespace QuickMedia { int next_page = tab_associated_data[selected_tab].fetched_page + 1; Page *page = tabs[selected_tab].page.get(); std::string update_search_text = tab_associated_data[selected_tab].update_search_text; - tab_associated_data[selected_tab].next_page_future = AsyncTask([update_search_text, next_page, page]() { + tab_associated_data[selected_tab].next_page_future = AsyncTask([update_search_text{std::move(update_search_text)}, next_page, page]() { BodyItems result_items; if(page->get_page(update_search_text, next_page, result_items) != PluginResult::OK) fprintf(stderr, "Failed to get next page (page %d)\n", next_page); @@ -2082,12 +2066,12 @@ namespace QuickMedia { } } - sf::Event event; - sf::Clock frame_timer; + mgl::Event event; + mgl::Clock frame_timer; - while (window.isOpen() && loop_running) { - sf::Int32 frame_time_ms = frame_timer.restart().asMilliseconds(); - while (window.pollEvent(event)) { + while (window.is_open() && loop_running) { + int32_t frame_time_ms = frame_timer.restart() * 1000.0; + while (window.poll_event(event)) { common_event_handler(event); const int selected_tab = ui_tabs.get_selected(); @@ -2096,31 +2080,29 @@ namespace QuickMedia { else event_idle_handler(event); - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); idle_active_handler(); } if(tabs[selected_tab].search_bar) { - tabs[selected_tab].search_bar->on_event(event); + tabs[selected_tab].search_bar->on_event(window, event); } ui_tabs.on_event(event); - if(event.type == sf::Event::Resized || event.type == sf::Event::GainedFocus) + if(event.type == mgl::Event::Resized || event.type == mgl::Event::GainedFocus) redraw = true; - else if(event.type == sf::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::Escape && go_to_previous_on_escape) { + else if(event.type == mgl::Event::KeyPressed) { + if(event.key.code == mgl::Keyboard::Escape && go_to_previous_on_escape) { return false; - } else if(event.key.code == sf::Keyboard::Enter) { + } else if(event.key.code == mgl::Keyboard::Enter) { if(!tabs[selected_tab].search_bar) { BodyItem *selected_item = tabs[selected_tab].body->get_selected(); submit_handler(selected_item ? selected_item->get_title() : ""); } - } else if(event.key.code == sf::Keyboard::T && event.key.control) { + } else if(event.key.code == mgl::Keyboard::T && event.key.control) { BodyItem *selected_item = tabs[selected_tab].body->get_selected(); if(selected_item && tabs[selected_tab].page->is_trackable()) { TrackablePage *trackable_page = dynamic_cast(tabs[selected_tab].page.get()); @@ -2128,7 +2110,7 @@ namespace QuickMedia { return trackable_page->track(selected_item->get_title()) == TrackResult::OK; }); } - } else if(event.key.code == sf::Keyboard::B && event.key.control) { + } else if(event.key.code == mgl::Keyboard::B && event.key.control) { auto bookmark_item = tabs[selected_tab].page->get_bookmark_body_item(); if(!bookmark_item) bookmark_item = tabs[selected_tab].body->get_selected_shared(); @@ -2143,15 +2125,15 @@ namespace QuickMedia { } } } - } else if(event.key.code == sf::Keyboard::C && event.key.control) { + } else if(event.key.code == mgl::Keyboard::C && event.key.control) { BodyItem *selected_item = tabs[selected_tab].body->get_selected(); if(selected_item) tabs[selected_tab].page->copy_to_clipboard(selected_item); - } else if(event.key.code == sf::Keyboard::I && event.key.control) { + } else if(event.key.code == mgl::Keyboard::I && event.key.control) { BodyItem *selected_item = tabs[selected_tab].body->get_selected(); if(show_info_page(selected_item, false)) redraw = true; - } else if(event.key.code == sf::Keyboard::Tab && !event.key.control) { + } else if(event.key.code == mgl::Keyboard::Tab && !event.key.control) { set_search_bar_to_body_item_text(tabs[selected_tab].body->get_selected(), tabs[selected_tab].search_bar.get()); } } @@ -2159,14 +2141,14 @@ namespace QuickMedia { update_idle_state(); handle_x11_events(); - if(!loop_running || !window.isOpen()) + if(!loop_running || !window.is_open()) break; const int selected_tab = ui_tabs.get_selected(); if(redraw) { redraw = false; - if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->onWindowResize(window_size); + if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->onWindowResize(window_size.to_vec2f()); // TODO: Dont show tabs if there is only one tab get_body_dimensions(window_size, tabs[selected_tab].search_bar.get(), body_pos, body_size, true); @@ -2200,7 +2182,7 @@ namespace QuickMedia { if(tab_associated_data[selected_tab].fetching_next_page_running) { double progress = 0.5 + std::sin(std::fmod(gradient_inc, 360.0) * 0.017453292519943295 - 1.5707963267948966*0.5) * 0.5; gradient_inc += (frame_time_ms * 0.5); - sf::Color bottom_color = interpolate_colors(get_theme().background_color, get_theme().loading_bar_color, progress); + mgl::Color bottom_color = interpolate_colors(get_theme().background_color, get_theme().loading_bar_color, progress); if(tabs[selected_tab].body->attach_side == AttachSide::TOP) { gradient_points[0].color = get_theme().background_color; @@ -2231,7 +2213,7 @@ namespace QuickMedia { if(tabs[selected_tab].page->is_ready() && tabs[selected_tab].page->is_lazy_fetch_page() && tab_associated_data[selected_tab].fetch_status == FetchStatus::NONE && !tab_associated_data[selected_tab].lazy_fetch_finished) { tab_associated_data[selected_tab].fetch_status = FetchStatus::LOADING; tab_associated_data[selected_tab].fetch_type = FetchType::LAZY; - tab_associated_data[selected_tab].search_result_text.setString("Loading..."); + tab_associated_data[selected_tab].search_result_text.set_string("Loading..."); LazyFetchPage *lazy_fetch_page = static_cast(tabs[selected_tab].page.get()); tab_associated_data[selected_tab].fetch_future = AsyncTask([lazy_fetch_page]() { FetchResult fetch_result; @@ -2287,10 +2269,10 @@ namespace QuickMedia { associated_data.search_text_updated = false; associated_data.fetch_status = FetchStatus::LOADING; associated_data.fetch_type = FetchType::SEARCH; - associated_data.search_result_text.setString("Searching..."); + associated_data.search_result_text.set_string("Searching..."); associated_data.search_suggestion_submitted = false; Page *page = tabs[i].page.get(); - associated_data.fetch_future = AsyncTask([update_search_text, page]() { + associated_data.fetch_future = AsyncTask([update_search_text{std::move(update_search_text)}, page]() { FetchResult fetch_result; fetch_result.result = search_result_to_plugin_result(page->search(update_search_text, fetch_result.body_items)); return fetch_result; @@ -2310,11 +2292,11 @@ namespace QuickMedia { associated_data.fetched_page = 0; associated_data.fetching_next_page_failed = false; if(fetch_result.result != PluginResult::OK) - associated_data.search_result_text.setString("Search failed!"); + associated_data.search_result_text.set_string("Search failed!"); else if(tabs[i].body->get_num_items() == 0) - associated_data.search_result_text.setString("No results found"); + associated_data.search_result_text.set_string("No results found"); else - associated_data.search_result_text.setString(""); + associated_data.search_result_text.set_string(""); idle_active_handler(); } else { associated_data.fetch_future.get(); @@ -2336,11 +2318,11 @@ namespace QuickMedia { } LazyFetchPage *lazy_fetch_page = static_cast(tabs[i].page.get()); if(fetch_result.result != PluginResult::OK) - associated_data.search_result_text.setString("Failed to fetch page!"); + associated_data.search_result_text.set_string("Failed to fetch page!"); else if(tabs[i].body->get_num_items() == 0 && !lazy_fetch_page->lazy_fetch_is_loader()) - associated_data.search_result_text.setString("No results found"); + associated_data.search_result_text.set_string("No results found"); else - associated_data.search_result_text.setString(""); + associated_data.search_result_text.set_string(""); associated_data.fetch_status = FetchStatus::NONE; idle_active_handler(); } @@ -2508,18 +2490,16 @@ namespace QuickMedia { AsyncTask task = callback; TaskResult task_result = TaskResult::TRUE; - window_size.x = window.getSize().x; - window_size.y = window.getSize().y; - sf::Event event; - while(window.isOpen()) { - while(window.pollEvent(event)) { + window_size.x = window.get_size().x; + window_size.y = window.get_size().y; + mgl::Event event; + while(window.is_open()) { + while(window.poll_event(event)) { common_event_handler(event); - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) { + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Escape) { task.cancel(); task_result = TaskResult::CANCEL; goto task_end; @@ -2539,8 +2519,8 @@ namespace QuickMedia { } window.clear(get_theme().background_color); - load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f); - load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0); + load_sprite.set_position(mgl::vec2f(window_size.x * 0.5f, window_size.y * 0.5f)); + load_sprite.set_rotation(load_sprite_timer.get_elapsed_time_seconds() * 400.0); window.draw(load_sprite); window.display(); } @@ -2573,7 +2553,7 @@ namespace QuickMedia { || is_soundcloud(url); } - void Program::video_page_download_video(const std::string &url, sf::WindowHandle video_player_window) { + void Program::video_page_download_video(const std::string &url, mgl::WindowHandle video_player_window) { bool separate_audio_option = url_should_download_with_youtube_dl(url); std::string video_id; separate_audio_option |= youtube_url_extract_id(url, video_id); @@ -2716,8 +2696,8 @@ namespace QuickMedia { move_in_parent = true; } - sf::WindowHandle video_player_window = None; - auto on_window_create = [this, &video_player_window, &video_loaded, &video_page](sf::WindowHandle _video_player_window) mutable { + mgl::WindowHandle video_player_window = None; + auto on_window_create = [this, &video_player_window, &video_loaded, &video_page](mgl::WindowHandle _video_player_window) mutable { video_player_window = _video_player_window; XSelectInput(disp, video_player_window, KeyPressMask | PointerMotionMask); XSync(disp, False); @@ -2908,8 +2888,7 @@ namespace QuickMedia { if(num_proxied_media > 0) { youtube_downloader_task = AsyncTask([&youtube_video_media_proxy, &youtube_audio_media_proxy]() { - sf::Clock timer; - const double sleep_time_millisec = 1; + mgl::Clock timer; // TODO: Poll instead of sleep while(!program_is_dead_in_current_thread()) { if(youtube_video_media_proxy) @@ -2918,16 +2897,16 @@ namespace QuickMedia { if(youtube_audio_media_proxy) youtube_audio_media_proxy->update(); - const int sleep_time = sleep_time_millisec - timer.restart().asMilliseconds(); - if(sleep_time > 0) - std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time)); + const double sleep_left_sec = timer.restart(); + if(sleep_left_sec > 0.000001) + std::this_thread::sleep_for(std::chrono::milliseconds((long)(sleep_left_sec * 1000.0))); } }); } } video_player = std::make_unique(is_audio_only, get_config().use_system_mpv_config, is_matrix && !is_youtube, video_event_callback, on_window_create, resources_root, video_max_height, plugin_name); - VideoPlayer::Error err = video_player->load_video(v.c_str(), a.c_str(), window.getSystemHandle(), use_youtube_dl, video_title, start_time, media_chapters); + VideoPlayer::Error err = video_player->load_video(v.c_str(), a.c_str(), window.get_system_handle(), use_youtube_dl, video_title, start_time, media_chapters); if(err != VideoPlayer::Error::OK) { std::string err_msg = "Failed to play url: "; err_msg += video_page->get_url(); @@ -2999,11 +2978,11 @@ namespace QuickMedia { load_video_error_check(); - sf::Event event; + mgl::Event event; XEvent xev; bool cursor_visible = true; - sf::Clock cursor_hide_timer; + mgl::Clock cursor_hide_timer; auto save_video_url_to_clipboard = [this, video_page]() { std::string url = video_page->get_download_url(video_get_max_height()); @@ -3016,33 +2995,31 @@ namespace QuickMedia { if((int)time_in_file > 0) clipboard += "&t=" + std::to_string((int)time_in_file); - sf::Clipboard::setString(sf::String::fromUtf8(clipboard.begin(), clipboard.end())); + set_clipboard(clipboard); } else { - sf::Clipboard::setString(sf::String::fromUtf8(url.begin(), url.end())); + set_clipboard(url); } }; - while (current_page == PageType::VIDEO_CONTENT && window.isOpen() && !go_to_previous_page) { - while (window.pollEvent(event)) { + while (current_page == PageType::VIDEO_CONTENT && window.is_open() && !go_to_previous_page) { + while (window.poll_event(event)) { common_event_handler(event); - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); - } else if(event.type == sf::Event::KeyPressed && (event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::Q || event.key.code == sf::Keyboard::Backspace)) { + } else if(event.type == mgl::Event::KeyPressed && (event.key.code == mgl::Keyboard::Escape || event.key.code == mgl::Keyboard::Q || event.key.code == mgl::Keyboard::Backspace)) { // To be able to close the video player while the video is loading - if(window_is_fullscreen(disp, window.getSystemHandle())) { - window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::UNSET); + if(window_is_fullscreen(disp, window.get_system_handle())) { + window_set_fullscreen(disp, window.get_system_handle(), WindowFullscreenState::UNSET); } else { current_page = previous_page; go_to_previous_page = true; } - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::F && event.key.control) { - window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::TOGGLE); - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::C && event.key.control) { + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::F && event.key.control) { + window_set_fullscreen(disp, window.get_system_handle(), WindowFullscreenState::TOGGLE); + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::C && event.key.control) { save_video_url_to_clipboard(); - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::F5) { + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::F5) { load_video_error_check(); } } @@ -3057,15 +3034,15 @@ namespace QuickMedia { if(pressed_keysym == XK_q && pressing_ctrl) { window.close(); } else if(pressed_keysym == XK_Escape || pressed_keysym == XK_q || pressed_keysym == XK_BackSpace) { - if(window_is_fullscreen(disp, window.getSystemHandle())) { - window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::UNSET); + if(window_is_fullscreen(disp, window.get_system_handle())) { + window_set_fullscreen(disp, window.get_system_handle(), WindowFullscreenState::UNSET); } else { current_page = previous_page; go_to_previous_page = true; break; } } else if(pressed_keysym == XK_f && pressing_ctrl) { - window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::TOGGLE); + window_set_fullscreen(disp, window.get_system_handle(), WindowFullscreenState::TOGGLE); } else if(pressed_keysym == XK_s && pressing_ctrl) { video_page_download_video(video_page->get_download_url(video_get_max_height()), video_player_window); } else if(pressed_keysym == XK_F5) { @@ -3077,6 +3054,7 @@ namespace QuickMedia { if(video_tasks.valid()) { XUnmapWindow(disp, video_player_window); XSync(disp, False); + XFlush(disp); TaskResult task_result = run_task_with_loading_screen([video_page, &related_videos]() { related_videos = video_page->get_related_media(video_page->get_url()); @@ -3092,7 +3070,7 @@ namespace QuickMedia { if(!cancelled) { if(!cursor_visible) - window.setMouseCursorVisible(true); + window.set_cursor_visible(true); cursor_visible = true; XUnmapWindow(disp, video_player_window); @@ -3108,6 +3086,10 @@ namespace QuickMedia { XSync(disp, False); show_notification("QuickMedia", "Failed to get related pages", Urgency::CRITICAL); } else if(related_pages_result == TaskResult::TRUE) { + XMapWindow(disp, video_player_window); + XSync(disp, False); + XFlush(disp); + bool page_changed = false; double resume_start_time = 0.0; page_loop(related_pages, video_page->get_related_pages_first_tab(), [&](const std::vector &new_tabs) { @@ -3128,7 +3110,7 @@ namespace QuickMedia { } }); - if(!window.isOpen() || current_page == PageType::EXIT) { + if(!window.is_open() || current_page == PageType::EXIT) { video_player.reset(); return; } @@ -3154,7 +3136,7 @@ namespace QuickMedia { while(XCheckTypedWindowEvent(disp, video_player_window, MotionNotify, &xev)); cursor_hide_timer.restart(); if(!cursor_visible) - window.setMouseCursorVisible(true); + window.set_cursor_visible(true); cursor_visible = true; } @@ -3270,14 +3252,14 @@ namespace QuickMedia { if(!video_loaded) { window.clear(get_theme().background_color); - load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f); - load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0); + load_sprite.set_position(mgl::vec2f(window_size.x * 0.5f, window_size.y * 0.5f)); + load_sprite.set_rotation(load_sprite_timer.get_elapsed_time_seconds() * 400.0); window.draw(load_sprite); window.display(); if(!cursor_visible) { cursor_visible = true; - window.setMouseCursorVisible(true); + window.set_cursor_visible(true); } cursor_hide_timer.restart(); continue; @@ -3289,20 +3271,20 @@ namespace QuickMedia { continue; } - const int UI_HIDE_TIMEOUT = 2500; - if(cursor_hide_timer.getElapsedTime().asMilliseconds() > UI_HIDE_TIMEOUT) { + const double UI_HIDE_TIMEOUT_SEC = 2.5; + if(cursor_hide_timer.get_elapsed_time_seconds() > UI_HIDE_TIMEOUT_SEC) { cursor_visible = false; - window.setMouseCursorVisible(false); + window.set_cursor_visible(false); } } std::this_thread::sleep_for(std::chrono::milliseconds(50)); } video_player.reset(); - window.setMouseCursorVisible(true); - window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::UNSET); + window.set_cursor_visible(true); + window_set_fullscreen(disp, window.get_system_handle(), WindowFullscreenState::UNSET); - auto window_size_u = window.getSize(); + auto window_size_u = window.get_size(); window_size.x = window_size_u.x; window_size.y = window_size_u.y; } @@ -3344,7 +3326,7 @@ namespace QuickMedia { // TODO: Optimize this somehow. One image alone uses more than 20mb ram! Total ram usage for viewing one image // becomes 40mb (private memory, almost 100mb in total!) Unacceptable! - Program::LoadImageResult Program::load_image_by_index(int image_index, sf::Texture &image_texture, sf::String &error_message) { + Program::LoadImageResult Program::load_image_by_index(int image_index, mgl::Texture &image_texture, std::string &error_message) { Path image_path = content_cache_dir; image_path.join(std::to_string(image_index + 1)); @@ -3357,16 +3339,8 @@ namespace QuickMedia { } if(get_file_type(image_path) == FileType::REGULAR && upscaled_ok) { - sf::Image image; - if(load_image_from_file(image, image_path.data)) { - if(image_texture.loadFromImage(image)) { - image_texture.setSmooth(true); - //image_texture.generateMipmap(); - return LoadImageResult::OK; - } else { - error_message = std::string("Failed to load image for page ") + std::to_string(image_index + 1); - return LoadImageResult::FAILED; - } + if(image_texture.load_from_file(image_path.data.c_str())) { + return LoadImageResult::OK; } else { show_notification("QuickMedia", "Failed to load image for page " + std::to_string(image_index + 1) + ". Image filepath: " + image_path.data, Urgency::CRITICAL); error_message = std::string("Failed to load image for page ") + std::to_string(image_index + 1); @@ -3501,18 +3475,16 @@ namespace QuickMedia { }); }, std::move(num_manga_pages_promise)); - sf::Event event; + mgl::Event event; PageType current_manga_page = current_page; - while (current_page == current_manga_page && window.isOpen()) { - while(window.pollEvent(event)) { + while (current_page == current_manga_page && window.is_open()) { + while(window.poll_event(event)) { common_event_handler(event); - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) { + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Escape) { current_page = pop_page_stack(); } } @@ -3524,8 +3496,8 @@ namespace QuickMedia { } window.clear(get_theme().background_color); - load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f); - load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0); + load_sprite.set_position(mgl::vec2f(window_size.x * 0.5f, window_size.y * 0.5f)); + load_sprite.set_rotation(load_sprite_timer.get_elapsed_time_seconds() * 400.0); window.draw(load_sprite); AsyncImageLoader::get_instance().update(); window.display(); @@ -3572,13 +3544,13 @@ namespace QuickMedia { return 0; } - sf::Texture image_texture; - sf::Sprite image; - sf::Text error_message("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(30 * get_config().scale * get_config().font_scale)); - error_message.setFillColor(get_theme().text_color); + mgl::Texture image_texture; + mgl::Sprite image; + mgl::Text error_message("", *FontLoader::get_font(FontLoader::FontType::LATIN, 30 * get_config().scale * get_config().font_scale)); + error_message.set_color(get_theme().text_color); bool download_in_progress = false; - sf::Event event; + mgl::Event event; download_chapter_images_if_needed(images_page); if(num_manga_pages == 0) { @@ -3586,7 +3558,7 @@ namespace QuickMedia { return 0; } - if(current_page != PageType::IMAGES || !window.isOpen()) + if(current_page != PageType::IMAGES || !window.is_open()) return 0; // TODO: Dont do this every time we change page? @@ -3596,57 +3568,56 @@ namespace QuickMedia { save_manga_progress(images_page, json_chapters, json_chapter, latest_read); if(image_index < num_manga_pages) { - sf::String error_msg; + std::string error_msg; LoadImageResult load_image_result = load_image_by_index(image_index, image_texture, error_msg); if(load_image_result == LoadImageResult::OK) - image.setTexture(image_texture, true); + image.set_texture(&image_texture); else if(load_image_result == LoadImageResult::DOWNLOAD_IN_PROGRESS) download_in_progress = true; - error_message.setString(error_msg); + error_message.set_string(std::move(error_msg)); } else if(image_index == num_manga_pages) { - error_message.setString("End of " + images_page->get_chapter_name()); + error_message.set_string("End of " + images_page->get_chapter_name()); } - bool error = !error_message.getString().isEmpty(); + bool error = !error_message.get_string().empty(); bool redraw = true; - sf::Text chapter_text(images_page->manga_name + " | " + images_page->get_chapter_name() + " | Page " + std::to_string(image_index + 1) + "/" + std::to_string(num_manga_pages), *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14 * get_config().scale * get_config().font_scale)); + const int chapter_text_character_size = 14 * get_config().scale * get_config().font_scale; + mgl::Text chapter_text(images_page->manga_name + " | " + images_page->get_chapter_name() + " | Page " + std::to_string(image_index + 1) + "/" + std::to_string(num_manga_pages), *FontLoader::get_font(FontLoader::FontType::LATIN, chapter_text_character_size)); if(image_index == num_manga_pages) - chapter_text.setString(images_page->manga_name + " | " + images_page->get_chapter_name() + " | End"); - chapter_text.setFillColor(sf::Color::White); - sf::RectangleShape chapter_text_background; - chapter_text_background.setFillColor(sf::Color(0, 0, 0, 150)); + chapter_text.set_string(images_page->manga_name + " | " + images_page->get_chapter_name() + " | End"); + chapter_text.set_color(mgl::Color(255, 255, 255, 255)); + mgl::Rectangle chapter_text_background; + chapter_text_background.set_color(mgl::Color(0, 0, 0, 150)); - sf::Vector2u texture_size; - sf::Vector2f texture_size_f; + mgl::vec2i texture_size; + mgl::vec2f texture_size_f; if(!error) { - texture_size = image.getTexture()->getSize(); - texture_size_f = sf::Vector2f(texture_size.x, texture_size.y); + texture_size = image.get_texture()->get_size(); + texture_size_f = mgl::vec2f(texture_size.x, texture_size.y); } - sf::Clock check_downloaded_timer; - const sf::Int32 check_downloaded_timeout_ms = 500; + mgl::Clock check_downloaded_timer; + const double check_downloaded_timeout_sec = 0.5; malloc_trim(0); - sf::Clock force_redraw_timer; - window.setFramerateLimit(20); + mgl::Clock force_redraw_timer; + window.set_framerate_limit(20); idle = true; // TODO: Show to user if a certain page is missing (by checking page name (number) and checking if some are skipped) - while (current_page == PageType::IMAGES && window.isOpen()) { - while(window.pollEvent(event)) { + while (current_page == PageType::IMAGES && window.is_open()) { + while(window.poll_event(event)) { common_event_handler(event); - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); redraw = true; - } else if(event.type == sf::Event::GainedFocus) { + } else if(event.type == mgl::Event::GainedFocus) { redraw = true; - } else if(event.type == sf::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::Up || (event.key.control && event.key.code == sf::Keyboard::K)) { + } else if(event.type == mgl::Event::KeyPressed) { + if(event.key.code == mgl::Keyboard::Up || (event.key.control && event.key.code == mgl::Keyboard::K)) { if(image_index > 0) { --image_index; goto end_of_images_page; @@ -3654,7 +3625,7 @@ namespace QuickMedia { page_navigation = -1; goto end_of_images_page; } - } else if(event.key.code == sf::Keyboard::Down || (event.key.control && event.key.code == sf::Keyboard::J)) { + } else if(event.key.code == mgl::Keyboard::Down || (event.key.control && event.key.code == mgl::Keyboard::J)) { if(image_index < num_manga_pages) { ++image_index; goto end_of_images_page; @@ -3662,12 +3633,12 @@ namespace QuickMedia { page_navigation = 1; goto end_of_images_page; } - } else if(event.key.code == sf::Keyboard::Escape) { + } else if(event.key.code == mgl::Keyboard::Escape) { current_page = pop_page_stack(); - } else if(event.key.code == sf::Keyboard::I) { + } else if(event.key.code == mgl::Keyboard::I) { current_page = PageType::IMAGES_CONTINUOUS; image_view_mode = ImageViewMode::SCROLL; - } else if(event.key.code == sf::Keyboard::F) { + } else if(event.key.code == mgl::Keyboard::F) { fit_image_to_window = !fit_image_to_window; redraw = true; } @@ -3675,33 +3646,33 @@ namespace QuickMedia { } handle_x11_events(); - if(download_in_progress && check_downloaded_timer.getElapsedTime().asMilliseconds() >= check_downloaded_timeout_ms) { - sf::String error_msg; + if(download_in_progress && check_downloaded_timer.get_elapsed_time_seconds() >= check_downloaded_timeout_sec) { + std::string error_msg; LoadImageResult load_image_result = load_image_by_index(image_index, image_texture, error_msg); if(load_image_result == LoadImageResult::OK) { - image.setTexture(image_texture, true); + image.set_texture(&image_texture); download_in_progress = false; error = false; - texture_size = image.getTexture()->getSize(); - texture_size_f = sf::Vector2f(texture_size.x, texture_size.y); + texture_size = image.get_texture()->get_size(); + texture_size_f = mgl::vec2f(texture_size.x, texture_size.y); } else if(load_image_result == LoadImageResult::FAILED) { download_in_progress = false; error = true; } - error_message.setString(error_msg); + error_message.set_string(std::move(error_msg)); redraw = true; check_downloaded_timer.restart(); } - const float font_height = chapter_text.getCharacterSize() + 8.0f; + const float font_height = chapter_text_character_size + 8.0f; const float bottom_panel_height = font_height + 6.0f; - sf::Vector2f content_size; + mgl::vec2f content_size; content_size.x = window_size.x; content_size.y = window_size.y - bottom_panel_height; // TODO: Track x11 window damage instead - if(force_redraw_timer.getElapsedTime().asSeconds() >= 1.0f) { + if(force_redraw_timer.get_elapsed_time_seconds() >= 1.0f) { force_redraw_timer.restart(); redraw = true; } @@ -3709,20 +3680,20 @@ namespace QuickMedia { if(redraw) { redraw = false; if(error) { - auto bounds = error_message.getLocalBounds(); - error_message.setPosition(vec2f_floor(content_size.x * 0.5f - bounds.width * 0.5f, content_size.y * 0.5f - bounds.height)); + auto bounds = error_message.get_bounds(); + error_message.set_position(vec2f_floor(content_size.x * 0.5f - bounds.size.x * 0.5f, content_size.y * 0.5f - bounds.size.y)); } else { - sf::Vector2f image_scale; + mgl::vec2f image_scale; if(fit_image_to_window) image_scale = get_ratio(texture_size_f, wrap_to_size(texture_size_f, content_size)); else image_scale = get_ratio(texture_size_f, clamp_to_size(texture_size_f, content_size)); - image.setScale(image_scale); + image.set_scale(image_scale); auto image_size = texture_size_f; image_size.x *= image_scale.x; image_size.y *= image_scale.y; - image.setPosition(vec2f_floor(content_size.x * 0.5f - image_size.x * 0.5f, content_size.y * 0.5f - image_size.y * 0.5f)); + image.set_position(vec2f_floor(content_size.x * 0.5f - image_size.x * 0.5f, content_size.y * 0.5f - image_size.y * 0.5f)); } window.clear(get_theme().background_color); @@ -3733,12 +3704,12 @@ namespace QuickMedia { window.draw(image); } - chapter_text_background.setSize(sf::Vector2f(window_size.x, bottom_panel_height)); - chapter_text_background.setPosition(0.0f, std::floor(window_size.y - bottom_panel_height)); + chapter_text_background.set_size(mgl::vec2f(window_size.x, bottom_panel_height)); + chapter_text_background.set_position(mgl::vec2f(0.0f, std::floor(window_size.y - bottom_panel_height))); window.draw(chapter_text_background); - auto text_bounds = chapter_text.getLocalBounds(); - chapter_text.setPosition(vec2f_floor(window_size.x * 0.5f - text_bounds.width * 0.5f, window_size.y - bottom_panel_height * 0.5f - font_height * 0.5f)); + auto text_bounds = chapter_text.get_bounds(); + chapter_text.set_position(vec2f_floor(window_size.x * 0.5f - text_bounds.size.x * 0.5f, window_size.y - bottom_panel_height * 0.5f - font_height * 0.6f)); window.draw(chapter_text); window.display(); @@ -3767,7 +3738,7 @@ namespace QuickMedia { return; } - if(current_page != PageType::IMAGES_CONTINUOUS || !window.isOpen()) + if(current_page != PageType::IMAGES_CONTINUOUS || !window.is_open()) return; Json::Value json_chapters; @@ -3778,7 +3749,7 @@ namespace QuickMedia { idle_active_handler(); - while(current_page == PageType::IMAGES_CONTINUOUS && window.isOpen()) { + while(current_page == PageType::IMAGES_CONTINUOUS && window.is_open()) { handle_x11_events(); window.clear(get_theme().background_color); ImageViewerAction action = image_viewer.draw(); @@ -3809,8 +3780,8 @@ namespace QuickMedia { } } - window_size.x = window.getSize().x; - window_size.y = window.getSize().y; + window_size.x = window.get_size().x; + window_size.y = window.get_size().y; } static bool get_image_board_last_posted_filepath(const char *plugin_name, Path &path) { @@ -3826,19 +3797,19 @@ namespace QuickMedia { float zoom = 1.0f; bool pressed = false; bool moved = false; - sf::Vector2f offset; // relative to center - sf::Vector2i prev_mouse_pos; + mgl::vec2f offset; // relative to center + mgl::vec2i prev_mouse_pos; }; - static sf::Vector2f to_vec2f(sf::Vector2i vec) { - return sf::Vector2f(vec.x, vec.y); + static mgl::vec2f to_vec2f(mgl::vec2i vec) { + return mgl::vec2f(vec.x, vec.y); } - static sf::Vector2f to_vec2f(sf::Vector2u vec) { - return sf::Vector2f(vec.x, vec.y); + static mgl::vec2f to_vec2f(mgl::vec2u vec) { + return mgl::vec2f(vec.x, vec.y); } - static sf::Vector2f floor(sf::Vector2f vec) { + static mgl::vec2f floor(mgl::vec2f vec) { return { std::floor(vec.x), std::floor(vec.y) }; } @@ -3856,10 +3827,10 @@ namespace QuickMedia { thread_body->title_mark_urls = true; NavigationStage navigation_stage = NavigationStage::VIEWING_COMMENTS; - sf::Texture captcha_texture; - sf::Sprite captcha_sprite; - sf::Texture captcha_bg_texture; - sf::Sprite captcha_bg_sprite; + mgl::Texture captcha_texture; + mgl::Sprite captcha_sprite; + mgl::Texture captcha_bg_texture; + mgl::Sprite captcha_bg_sprite; bool has_captcha_bg = false; float captcha_slide = 0.0f; std::string attached_image_url; @@ -3867,26 +3838,23 @@ namespace QuickMedia { ImageControl image_control; - captcha_texture.setSmooth(true); - captcha_bg_texture.setSmooth(true); - const float captcha_slide_padding_x = std::floor(4.0f * get_config().scale); const float captcha_slide_padding_y = std::floor(4.0f * get_config().scale); - sf::Color background_color_darker = get_theme().background_color; + mgl::Color background_color_darker = get_theme().background_color; background_color_darker.r = std::max(0, (int)background_color_darker.r - 20); background_color_darker.g = std::max(0, (int)background_color_darker.g - 20); background_color_darker.b = std::max(0, (int)background_color_darker.b - 20); - RoundedRectangle captcha_slide_bg(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale), background_color_darker, &rounded_rectangle_shader); - RoundedRectangle captcha_slide_fg(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale - captcha_slide_padding_y), get_theme().loading_bar_color, &rounded_rectangle_shader); + RoundedRectangle captcha_slide_bg(mgl::vec2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale), background_color_darker, &rounded_rectangle_shader); + RoundedRectangle captcha_slide_fg(mgl::vec2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale - captcha_slide_padding_y), get_theme().loading_bar_color, &rounded_rectangle_shader); - auto attached_image_texture = std::make_unique(); - sf::Sprite attached_image_sprite; + auto attached_image_texture = std::make_unique(); + mgl::Sprite attached_image_sprite; std::string captcha_post_id; std::string captcha_solution; std::string comment_to_post; const int captcha_solution_text_height = 18 * get_config().scale * get_config().font_scale; - sf::Text captcha_solution_text("", *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD), captcha_solution_text_height); + mgl::Text captcha_solution_text("", *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD, captcha_solution_text_height)); int solved_captcha_ttl = 0; int64_t last_posted_time = time(nullptr); int64_t seconds_until_post_again = 60; // TODO: Timeout for other imageboards @@ -3983,14 +3951,14 @@ namespace QuickMedia { return false; }; - sf::RectangleShape comment_input_shade; - comment_input_shade.setFillColor(get_theme().shade_color); + mgl::Rectangle comment_input_shade; + comment_input_shade.set_color(get_theme().shade_color); - sf::Sprite logo_sprite(plugin_logo); - logo_sprite.setScale(0.8f * get_config().scale, 0.8f * get_config().scale); - sf::Vector2f logo_size(std::floor(plugin_logo.getSize().x * logo_sprite.getScale().x), std::floor(plugin_logo.getSize().y * logo_sprite.getScale().y)); + mgl::Sprite logo_sprite(&plugin_logo); + logo_sprite.set_scale(mgl::vec2f(0.8f * get_config().scale, 0.8f * get_config().scale)); + mgl::vec2f logo_size(std::floor(plugin_logo.get_size().x * logo_sprite.get_scale().x), std::floor(plugin_logo.get_size().y * logo_sprite.get_scale().y)); - sf::Sprite file_to_upload_sprite; + mgl::Sprite file_to_upload_sprite; bool sprite_applied_texture = false; std::shared_ptr file_to_upload_thumbnail_data; @@ -4002,17 +3970,17 @@ namespace QuickMedia { const float chat_input_padding_x = std::floor(10.0f * get_config().scale); const float chat_input_padding_y = std::floor(10.0f * get_config().scale); - sf::Vector2f body_pos; - sf::Vector2f body_size; - sf::Event event; + mgl::vec2f body_pos; + mgl::vec2f body_size; + mgl::Event event; std::deque comment_navigation_stack; std::deque comment_page_scroll_stack; - sf::Clock frame_timer; - while (current_page == PageType::IMAGE_BOARD_THREAD && window.isOpen()) { - const float frame_elapsed_time_sec = frame_timer.restart().asSeconds(); - while (window.pollEvent(event)) { + mgl::Clock frame_timer; + while (current_page == PageType::IMAGE_BOARD_THREAD && window.is_open()) { + const float frame_elapsed_time_sec = frame_timer.restart(); + while (window.poll_event(event)) { common_event_handler(event); if(navigation_stage == NavigationStage::REPLYING || navigation_stage == NavigationStage::VIEWING_COMMENTS) { if(thread_body->on_event(window, event, navigation_stage == NavigationStage::VIEWING_COMMENTS)) @@ -4021,30 +3989,28 @@ namespace QuickMedia { event_idle_handler(event); if(!frame_skip_text_entry) - comment_input.process_event(event); + comment_input.process_event(window, event); if(navigation_stage == NavigationStage::REPLYING && !frame_skip_text_entry) { - if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) { + if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Escape) { comment_input.set_editable(false); navigation_stage = NavigationStage::VIEWING_COMMENTS; break; } } - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); idle_active_handler(); } - if(event.type == sf::Event::Resized || event.type == sf::Event::GainedFocus) + if(event.type == mgl::Event::Resized || event.type == mgl::Event::GainedFocus) redraw = true; - else if(navigation_stage == NavigationStage::VIEWING_COMMENTS && event.type == sf::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::Escape) { + else if(navigation_stage == NavigationStage::VIEWING_COMMENTS && event.type == mgl::Event::KeyPressed) { + if(event.key.code == mgl::Keyboard::Escape) { current_page = pop_page_stack(); - } else if(event.key.code == sf::Keyboard::P) { + } else if(event.key.code == mgl::Keyboard::P) { BodyItem *selected_item = thread_body->get_selected(); if(selected_item && !selected_item->url.empty()) { if(is_url_video(selected_item->url)) { @@ -4066,7 +4032,7 @@ namespace QuickMedia { BodyItem *selected_item = thread_body->get_selected(); if(selected_item && !selected_item->url.empty()) { attached_image_url = selected_item->url; - sf::Image image; + mgl::Image image; TaskResult task_result = run_task_with_loading_screen([&attached_image_url, &image]{ SHA256 sha256; sha256.add(attached_image_url.data(), attached_image_url.size()); @@ -4077,7 +4043,7 @@ namespace QuickMedia { return false; } - if(!load_image_from_file(image, media_file_path.data)) { + if(!image.load_from_file(media_file_path.data.c_str())) { show_notification("QuickMedia", "Failed to load image: " + attached_image_url, Urgency::CRITICAL); return false; } @@ -4085,20 +4051,21 @@ namespace QuickMedia { }); if(task_result == TaskResult::TRUE) { - attached_image_texture = std::make_unique(); - if(attached_image_texture->loadFromImage(image)) { - attached_image_texture->setSmooth(true); - attached_image_sprite.setTexture(*attached_image_texture, true); - attached_image_sprite.setOrigin(0.0f, 0.0f); - attached_image_sprite.setScale(1.0f, 1.0f); + attached_image_texture = std::make_unique(); + if(attached_image_texture->load_from_image(image)) { + attached_image_sprite.set_texture(attached_image_texture.get()); + attached_image_sprite.set_origin(mgl::vec2f(0.0f, 0.0f)); + attached_image_sprite.set_scale(mgl::vec2f(1.0f, 1.0f)); navigation_stage = NavigationStage::VIEWING_ATTACHED_IMAGE; image_control.zoom = 1.0f; - image_control.offset = to_vec2f(attached_image_texture->getSize()) * 0.5f; - image_control.pressed = sf::Mouse::isButtonPressed(sf::Mouse::Left); + image_control.offset = to_vec2f(attached_image_texture->get_size()) * 0.5f; + image_control.pressed = window.is_mouse_button_pressed(mgl::Mouse::Left); + image_control.pressed = false; + image_control.moved = false; if(image_control.pressed) - image_control.prev_mouse_pos = sf::Mouse::getPosition(window); + image_control.prev_mouse_pos = window.get_mouse_position(); } else { show_notification("QuickMedia", "Failed to load image: " + attached_image_url, Urgency::CRITICAL); } @@ -4106,7 +4073,7 @@ namespace QuickMedia { } } } - } else if(event.key.code == sf::Keyboard::U) { + } else if(event.key.code == mgl::Keyboard::U) { std::filesystem::path &fm_dir = file_manager_start_dir; auto file_manager_page = std::make_unique(this, (FileManagerMimeType)(FILE_MANAGER_MIME_TYPE_IMAGE|FILE_MANAGER_MIME_TYPE_VIDEO)); file_manager_page->set_current_directory(fm_dir.string()); @@ -4117,8 +4084,8 @@ namespace QuickMedia { std::vector file_manager_tabs; file_manager_tabs.push_back(Tab{std::move(file_manager_body), std::move(file_manager_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); - sf::Event event; - while(window.pollEvent(event)) { common_event_handler(event); } + mgl::Event event; + while(window.poll_event(event)) { common_event_handler(event); } selected_files.clear(); page_loop(file_manager_tabs); @@ -4131,26 +4098,26 @@ namespace QuickMedia { redraw = true; frame_skip_text_entry = true; - } else if(event.key.code == sf::Keyboard::D && event.key.control) { + } else if(event.key.code == mgl::Keyboard::D && event.key.control) { selected_file_for_upload.clear(); - } else if(event.key.code == sf::Keyboard::C && event.key.control) { + } else if(event.key.code == mgl::Keyboard::C && event.key.control) { BodyItem *selected_item = thread_body->get_selected(); if(selected_item) thread_page->copy_to_clipboard(selected_item); - } else if(event.key.code == sf::Keyboard::I && event.key.control) { + } else if(event.key.code == mgl::Keyboard::I && event.key.control) { BodyItem *selected_item = thread_body->get_selected(); if(show_info_page(selected_item, true)) { redraw = true; frame_skip_text_entry = true; } - } else if(event.key.code == sf::Keyboard::S && event.key.control) { + } else if(event.key.code == mgl::Keyboard::S && event.key.control) { BodyItem *selected_item = thread_body->get_selected(); if(selected_item && !selected_item->url.empty()) download_async_gui(selected_item->url, file_manager_start_dir.string(), false); } BodyItem *selected_item = thread_body->get_selected(); - if(event.key.code == sf::Keyboard::Enter && selected_item && (comment_navigation_stack.empty() || thread_body->get_selected_item() != comment_navigation_stack.back()) && (!selected_item->replies_to.empty() || !selected_item->replies.empty())) { + if(event.key.code == mgl::Keyboard::Enter && selected_item && (comment_navigation_stack.empty() || thread_body->get_selected_item() != comment_navigation_stack.back()) && (!selected_item->replies_to.empty() || !selected_item->replies.empty())) { thread_body->for_each_item([](std::shared_ptr &body_item) { body_item->visible = false; }); @@ -4165,7 +4132,7 @@ namespace QuickMedia { comment_page_scroll_stack.push_back(thread_body->get_page_scroll()); //thread_body->clamp_selection(); thread_body->set_page_scroll(0.0f); - } else if(event.key.code == sf::Keyboard::BackSpace && !comment_navigation_stack.empty()) { + } else if(event.key.code == mgl::Keyboard::Backspace && !comment_navigation_stack.empty()) { size_t previous_selected = comment_navigation_stack.back(); float previous_page_scroll = comment_page_scroll_stack.back(); comment_navigation_stack.pop_back(); @@ -4192,13 +4159,13 @@ namespace QuickMedia { thread_body->clamp_selection(); } thread_body->set_page_scroll(previous_page_scroll); - } else if(event.key.code == sf::Keyboard::R && selected_item) { + } else if(event.key.code == mgl::Keyboard::R && selected_item) { std::string text_to_add = ">>" + selected_item->post_number + "\n"; - comment_input.append_text(std::move(text_to_add)); + comment_input.insert_text_at_caret_position(std::move(text_to_add)); comment_input.move_caret_to_end(); } - if(event.key.code == sf::Keyboard::I && !event.key.control) { + if(event.key.code == mgl::Keyboard::I && !event.key.control) { frame_skip_text_entry = true; navigation_stage = NavigationStage::REPLYING; comment_input.set_editable(true); @@ -4206,75 +4173,74 @@ namespace QuickMedia { } } - if(event.type == sf::Event::KeyPressed && navigation_stage == NavigationStage::SOLVING_POST_CAPTCHA && !frame_skip_text_entry) { - if(event.key.code == sf::Keyboard::Escape) { + if(event.type == mgl::Event::KeyPressed && navigation_stage == NavigationStage::SOLVING_POST_CAPTCHA && !frame_skip_text_entry) { + if(event.key.code == mgl::Keyboard::Escape) { navigation_stage = NavigationStage::VIEWING_COMMENTS; - } else if(event.key.code == sf::Keyboard::Enter) { + } else if(event.key.code == mgl::Keyboard::Enter) { navigation_stage = NavigationStage::POSTING_COMMENT; - auto str8 = captcha_solution_text.getString().toUtf8(); - captcha_solution.assign(str8.begin(), str8.end()); - } else if(event.key.code == sf::Keyboard::BackSpace) { - auto str = captcha_solution_text.getString(); - if(!str.isEmpty()) { - str.erase(str.getSize() - 1); - captcha_solution_text.setString(std::move(str)); + captcha_solution = captcha_solution_text.get_string(); + } else if(event.key.code == mgl::Keyboard::Backspace) { + std::string str = captcha_solution_text.get_string(); + if(!str.empty()) { + str.erase(str.size() - 1); + captcha_solution_text.set_string(std::move(str)); } } else { - const int alpha = (int)event.key.code - (int)sf::Keyboard::A; - const int num = (int)event.key.code - (int)sf::Keyboard::Num0; - const int numpad = (int)event.key.code - (int)sf::Keyboard::Numpad0; - if(alpha >= 0 && alpha <= sf::Keyboard::Z - sf::Keyboard::A) { - captcha_solution_text.setString(captcha_solution_text.getString() + (sf::Uint32)to_upper(alpha + 'a')); - } else if(num >= 0 && num <= sf::Keyboard::Num9 - sf::Keyboard::Num0) { - captcha_solution_text.setString(captcha_solution_text.getString() + (sf::Uint32)(num + '0')); - } else if(numpad >= 0 && numpad <= sf::Keyboard::Numpad9 - sf::Keyboard::Numpad0) { - captcha_solution_text.setString(captcha_solution_text.getString() + (sf::Uint32)(numpad + '0')); + const int alpha = (int)event.key.code - (int)mgl::Keyboard::A; + const int num = (int)event.key.code - (int)mgl::Keyboard::Num0; + const int numpad = (int)event.key.code - (int)mgl::Keyboard::Numpad0; + if(alpha >= 0 && alpha <= mgl::Keyboard::Z - mgl::Keyboard::A) { + captcha_solution_text.set_string(captcha_solution_text.get_string() + (char)to_upper(alpha + 'a')); + } else if(num >= 0 && num <= mgl::Keyboard::Num9 - mgl::Keyboard::Num0) { + captcha_solution_text.set_string(captcha_solution_text.get_string() + (char)(num + '0')); + } else if(numpad >= 0 && numpad <= mgl::Keyboard::Numpad9 - mgl::Keyboard::Numpad0) { + captcha_solution_text.set_string(captcha_solution_text.get_string() + (char)(numpad + '0')); } } } if(navigation_stage == NavigationStage::VIEWING_ATTACHED_IMAGE) { - if(event.type == sf::Event::MouseWheelScrolled) { - image_control.zoom *= (1.0f + event.mouseWheelScroll.delta * 0.1f); + if(event.type == mgl::Event::MouseWheelScrolled) { + image_control.zoom *= (1.0f + event.mouse_wheel_scroll.delta * 0.1f); if(image_control.zoom < 0.01f) image_control.zoom = 0.01f; image_control.moved = true; - } else if(event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) { + } else if(event.type == mgl::Event::MouseButtonPressed && event.mouse_button.button == mgl::Mouse::Left) { image_control.pressed = true; - image_control.prev_mouse_pos.x = event.mouseButton.x; - image_control.prev_mouse_pos.y = event.mouseButton.y; - } else if(event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left) { + image_control.prev_mouse_pos.x = event.mouse_button.x; + image_control.prev_mouse_pos.y = event.mouse_button.y; + } else if(event.type == mgl::Event::MouseButtonReleased && event.mouse_button.button == mgl::Mouse::Left) { image_control.pressed = false; - } else if(event.type == sf::Event::MouseMoved && image_control.pressed) { - const sf::Vector2i mouse_diff = sf::Vector2i(event.mouseMove.x, event.mouseMove.y) - image_control.prev_mouse_pos; - image_control.prev_mouse_pos.x = event.mouseMove.x; - image_control.prev_mouse_pos.y = event.mouseMove.y; + } else if(event.type == mgl::Event::MouseMoved && image_control.pressed) { + const mgl::vec2i mouse_diff = mgl::vec2i(event.mouse_move.x, event.mouse_move.y) - image_control.prev_mouse_pos; + image_control.prev_mouse_pos.x = event.mouse_move.x; + image_control.prev_mouse_pos.y = event.mouse_move.y; image_control.offset -= (to_vec2f(mouse_diff) / image_control.zoom); image_control.moved = true; idle_active_handler(); - } else if(event.type == sf::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::W) { + } else if(event.type == mgl::Event::KeyPressed) { + if(event.key.code == mgl::Keyboard::W) { image_control.zoom = 1.0f; image_control.moved = false; - image_control.offset = to_vec2f(attached_image_texture->getSize()) * 0.5f; - attached_image_sprite.setOrigin(0.0f, 0.0f); - attached_image_sprite.setScale(1.0f, 1.0f); + image_control.offset = to_vec2f(attached_image_texture->get_size()) * 0.5f; + attached_image_sprite.set_origin(mgl::vec2f(0.0f, 0.0f)); + attached_image_sprite.set_scale(mgl::vec2f(1.0f, 1.0f)); } } } - if(event.type == sf::Event::KeyPressed && navigation_stage == NavigationStage::VIEWING_ATTACHED_IMAGE) { - if(event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::BackSpace) { + if(event.type == mgl::Event::KeyPressed && navigation_stage == NavigationStage::VIEWING_ATTACHED_IMAGE) { + if(event.key.code == mgl::Keyboard::Escape || event.key.code == mgl::Keyboard::Backspace) { navigation_stage = NavigationStage::VIEWING_COMMENTS; - attached_image_texture.reset(new sf::Texture()); + attached_image_texture.reset(new mgl::Texture()); redraw = true; - } else if(event.key.code == sf::Keyboard::I && event.key.control && !attached_image_url.empty()) { + } else if(event.key.code == mgl::Keyboard::I && event.key.control && !attached_image_url.empty()) { std::vector saucenao_tabs; saucenao_tabs.push_back(Tab{create_body(), std::make_unique(this, attached_image_url, false), nullptr}); page_loop(saucenao_tabs); redraw = true; frame_skip_text_entry = true; - } else if(event.key.code == sf::Keyboard::S && event.key.control) { + } else if(event.key.code == mgl::Keyboard::S && event.key.control) { download_async_gui(attached_image_url, file_manager_start_dir.string(), false); } } @@ -4293,7 +4259,7 @@ namespace QuickMedia { comment_input.set_editable(false); captcha_post_id = std::move(captcha_challenge.challenge_id); solved_captcha_ttl = 0;// captcha_challenge.ttl; // TODO: Support ttl to not have to solve captcha again - captcha_solution_text.setString(""); + captcha_solution_text.set_string(""); captcha_slide = 0.0f; if(captcha_post_id == "noop") { // TODO: Fix for other imageboard than 4chan in the future @@ -4301,16 +4267,16 @@ namespace QuickMedia { navigation_stage = NavigationStage::POSTING_COMMENT; } else { bool failed = false; - sf::Image image; - if(!load_image_from_memory(image, captcha_challenge.img_data.data(), captcha_challenge.img_data.size()) || !captcha_texture.loadFromImage(image)) { + mgl::Image image; + if(!image.load_from_memory((const unsigned char*)captcha_challenge.img_data.data(), captcha_challenge.img_data.size()) || !captcha_texture.load_from_image(image)) { show_notification("QuickMedia", "Failed to load captcha image", Urgency::CRITICAL); failed = true; } captcha_challenge.img_data = std::string(); has_captcha_bg = !failed && !captcha_challenge.bg_data.empty(); - sf::Image bg_Image; - if(has_captcha_bg && (!load_image_from_memory(bg_Image, captcha_challenge.bg_data.data(), captcha_challenge.bg_data.size()) || !captcha_bg_texture.loadFromImage(bg_Image))) { + mgl::Image bg_image; + if(has_captcha_bg && (!bg_image.load_from_memory((const unsigned char*)captcha_challenge.bg_data.data(), captcha_challenge.bg_data.size()) || !captcha_bg_texture.load_from_image(bg_image))) { show_notification("QuickMedia", "Failed to load captcha image", Urgency::CRITICAL); failed = true; } @@ -4320,9 +4286,9 @@ namespace QuickMedia { navigation_stage = NavigationStage::VIEWING_COMMENTS; } else { navigation_stage = NavigationStage::SOLVING_POST_CAPTCHA; - captcha_sprite.setTexture(captcha_texture, true); + captcha_sprite.set_texture(&captcha_texture); if(has_captcha_bg) - captcha_bg_sprite.setTexture(captcha_bg_texture, true); + captcha_bg_sprite.set_texture(&captcha_bg_texture); } } } else if(task_result == TaskResult::CANCEL) { @@ -4351,13 +4317,12 @@ namespace QuickMedia { redraw = true; } } else { - file_to_upload_thumbnail_data = AsyncImageLoader::get_instance().get_thumbnail(selected_file_for_upload, true, sf::Vector2i(logo_size.x, logo_size.y * 4)); + file_to_upload_thumbnail_data = AsyncImageLoader::get_instance().get_thumbnail(selected_file_for_upload, true, mgl::vec2i(logo_size.x, logo_size.y * 4)); } - if(file_to_upload_thumbnail_data && file_to_upload_thumbnail_data->loading_state == LoadingState::FINISHED_LOADING && file_to_upload_thumbnail_data->image->getSize().x > 0 && file_to_upload_thumbnail_data->image->getSize().y > 0) { - if(!file_to_upload_thumbnail_data->texture.loadFromImage(*file_to_upload_thumbnail_data->image)) + if(file_to_upload_thumbnail_data && file_to_upload_thumbnail_data->loading_state == LoadingState::FINISHED_LOADING && file_to_upload_thumbnail_data->image->get_size().x > 0 && file_to_upload_thumbnail_data->image->get_size().y > 0) { + if(!file_to_upload_thumbnail_data->texture.load_from_image(*file_to_upload_thumbnail_data->image)) fprintf(stderr, "Warning: failed to load texture for attached file\n"); - file_to_upload_thumbnail_data->texture.setSmooth(true); //room_avatar_thumbnail_data->texture.generateMipmap(); file_to_upload_thumbnail_data->image.reset(); file_to_upload_thumbnail_data->loading_state = LoadingState::APPLIED_TO_TEXTURE; @@ -4365,18 +4330,18 @@ namespace QuickMedia { } if(file_to_upload_thumbnail_data && file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE && !sprite_applied_texture) { - file_to_upload_sprite.setTexture(file_to_upload_thumbnail_data->texture, true); + file_to_upload_sprite.set_texture(&file_to_upload_thumbnail_data->texture); sprite_applied_texture = true; - sf::Vector2f texture_size_f(file_to_upload_thumbnail_data->texture.getSize().x, file_to_upload_thumbnail_data->texture.getSize().y); - sf::Vector2f image_scale = get_ratio(texture_size_f, clamp_to_size_x(texture_size_f, logo_size)); - file_to_upload_sprite.setScale(image_scale); + mgl::vec2f texture_size_f(file_to_upload_thumbnail_data->texture.get_size().x, file_to_upload_thumbnail_data->texture.get_size().y); + mgl::vec2f image_scale = get_ratio(texture_size_f, clamp_to_size_x(texture_size_f, logo_size.x)); + file_to_upload_sprite.set_scale(image_scale); redraw = true; } float chat_input_height_full_images = logo_size.y; if(file_to_upload_thumbnail_data && file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE) { - const float file_to_upload_height = std::floor(logo_file_to_upload_spacing + file_to_upload_sprite.getTexture()->getSize().y * file_to_upload_sprite.getScale().y); + const float file_to_upload_height = std::floor(logo_file_to_upload_spacing + file_to_upload_sprite.get_texture()->get_size().y * file_to_upload_sprite.get_scale().y); chat_input_height_full_images += file_to_upload_height; } chat_input_height_full = chat_input_padding_y + std::max(comment_input.get_height(), chat_input_height_full_images) + chat_input_padding_y; @@ -4395,59 +4360,59 @@ namespace QuickMedia { const float body_width = window_size.x; - comment_input_shade.setSize(sf::Vector2f(window_size.x, chat_input_height_full)); - comment_input_shade.setPosition(0.0f, 0.0f); + comment_input_shade.set_size(mgl::vec2f(window_size.x, chat_input_height_full)); + comment_input_shade.set_position(mgl::vec2f(0.0f, 0.0f)); - body_pos = sf::Vector2f(0.0f, comment_input_shade.getSize().y); - body_size = sf::Vector2f(body_width, window_size.y - comment_input_shade.getSize().y); + body_pos = mgl::vec2f(0.0f, comment_input_shade.get_size().y); + body_size = mgl::vec2f(body_width, window_size.y - comment_input_shade.get_size().y); - logo_sprite.setPosition(logo_padding_x, chat_input_padding_y); - file_to_upload_sprite.setPosition(logo_sprite.getPosition() + sf::Vector2f(0.0f, logo_size.y + logo_file_to_upload_spacing)); + logo_sprite.set_position(mgl::vec2f(logo_padding_x, chat_input_padding_y)); + file_to_upload_sprite.set_position(logo_sprite.get_position() + mgl::vec2f(0.0f, logo_size.y + logo_file_to_upload_spacing)); } //comment_input.update(); window.clear(get_theme().background_color); - if(navigation_stage == NavigationStage::SOLVING_POST_CAPTCHA && captcha_texture.getNativeHandle() != 0) { + if(navigation_stage == NavigationStage::SOLVING_POST_CAPTCHA && captcha_texture.is_valid()) { const float slide_speed = 0.5f; - const bool window_has_focus = window.hasFocus(); - if(window_has_focus && sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { + const bool window_has_focus = window.has_focus(); + if(window_has_focus && window.is_key_pressed(mgl::Keyboard::Left)) { captcha_slide -= (slide_speed * frame_elapsed_time_sec); if(captcha_slide < 0.0f) captcha_slide = 0.0f; - } else if(window_has_focus && sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { + } else if(window_has_focus && window.is_key_pressed(mgl::Keyboard::Right)) { captcha_slide += (slide_speed * frame_elapsed_time_sec); if(captcha_slide > 1.0f) captcha_slide = 1.0f; } - sf::Vector2f content_size = window_size; + mgl::vec2f content_size = window_size.to_vec2f(); int image_height = 0; - sf::Vector2u captcha_texture_size = captcha_texture.getSize(); - sf::Vector2f captcha_texture_size_f(captcha_texture_size.x, captcha_texture_size.y); + mgl::vec2i captcha_texture_size = captcha_texture.get_size(); + mgl::vec2f captcha_texture_size_f(captcha_texture_size.x, captcha_texture_size.y); auto image_scale = get_ratio(captcha_texture_size_f, clamp_to_size(captcha_texture_size_f, content_size)); - captcha_sprite.setScale(image_scale); + captcha_sprite.set_scale(image_scale); auto captcha_image_size = captcha_texture_size_f; captcha_image_size.x *= image_scale.x; captcha_image_size.y *= image_scale.y; - captcha_sprite.setPosition(vec2f_floor(content_size.x * 0.5f - captcha_image_size.x * 0.5f, content_size.y * 0.5f - captcha_image_size.y * 0.5f)); + captcha_sprite.set_position(vec2f_floor(content_size.x * 0.5f - captcha_image_size.x * 0.5f, content_size.y * 0.5f - captcha_image_size.y * 0.5f)); image_height = (int)captcha_image_size.y; - if(has_captcha_bg && captcha_bg_texture.getNativeHandle() != 0) { - sf::Vector2f content_size = window_size; + if(has_captcha_bg && captcha_bg_texture.is_valid()) { + mgl::vec2f content_size = window_size.to_vec2f(); - sf::Vector2u captcha_bg_texture_size = captcha_bg_texture.getSize(); - sf::Vector2f captcha_bg_texture_size_f(captcha_bg_texture_size.x, captcha_bg_texture_size.y); + mgl::vec2i captcha_bg_texture_size = captcha_bg_texture.get_size(); + mgl::vec2f captcha_bg_texture_size_f(captcha_bg_texture_size.x, captcha_bg_texture_size.y); auto image_scale = get_ratio(captcha_bg_texture_size_f, clamp_to_size(captcha_bg_texture_size_f, content_size)); - captcha_bg_sprite.setScale(image_scale); + captcha_bg_sprite.set_scale(image_scale); auto image_size = captcha_bg_texture_size_f; image_size.x *= image_scale.x; image_size.y *= image_scale.y; const float width_diff = image_size.x - captcha_image_size.x; - captcha_bg_sprite.setPosition(vec2f_floor(captcha_sprite.getPosition().x + width_diff*1.0f - captcha_slide*(width_diff + width_diff*2.0f), captcha_sprite.getPosition().y)); + captcha_bg_sprite.set_position(vec2f_floor(captcha_sprite.get_position().x + width_diff*1.0f - captcha_slide*(width_diff + width_diff*2.0f), captcha_sprite.get_position().y)); window.draw(captcha_bg_sprite); image_height = std::max(image_height, (int)image_size.y); @@ -4456,64 +4421,64 @@ namespace QuickMedia { window.draw(captcha_sprite); // TODO: Cut off ends with sf::View instead - sf::RectangleShape cut_off_rectangle(captcha_image_size); - cut_off_rectangle.setFillColor(get_theme().background_color); - cut_off_rectangle.setPosition(captcha_sprite.getPosition() - sf::Vector2f(cut_off_rectangle.getSize().x, 0.0f)); + mgl::Rectangle cut_off_rectangle(captcha_image_size); + cut_off_rectangle.set_color(get_theme().background_color); + cut_off_rectangle.set_position(captcha_sprite.get_position() - mgl::vec2f(cut_off_rectangle.get_size().x, 0.0f)); window.draw(cut_off_rectangle); - cut_off_rectangle.setPosition(captcha_sprite.getPosition() + sf::Vector2f(captcha_image_size.x, 0.0f)); + cut_off_rectangle.set_position(captcha_sprite.get_position() + mgl::vec2f(captcha_image_size.x, 0.0f)); window.draw(cut_off_rectangle); const float captcha_slide_bg_height = std::floor(20.0f * get_config().scale); - captcha_slide_bg.set_size(sf::Vector2f(captcha_image_size.x, captcha_slide_bg_height)); - captcha_slide_bg.set_position(sf::Vector2f(captcha_sprite.getPosition().x, captcha_sprite.getPosition().y + image_height + 10.0f)); + captcha_slide_bg.set_size(mgl::vec2f(captcha_image_size.x, captcha_slide_bg_height)); + captcha_slide_bg.set_position(mgl::vec2f(captcha_sprite.get_position().x, captcha_sprite.get_position().y + image_height + 10.0f)); - const sf::Vector2f captcha_slide_fg_size = captcha_slide_bg.get_size() - sf::Vector2f(captcha_slide_padding_x * 2.0f, captcha_slide_padding_y * 2.0f); + const mgl::vec2f captcha_slide_fg_size = captcha_slide_bg.get_size() - mgl::vec2f(captcha_slide_padding_x * 2.0f, captcha_slide_padding_y * 2.0f); captcha_slide_fg.set_size(vec2f_floor(captcha_slide_fg_size.x * captcha_slide, captcha_slide_fg_size.y)); - captcha_slide_fg.set_position(captcha_slide_bg.get_position() + sf::Vector2f(captcha_slide_padding_x, captcha_slide_padding_y)); + captcha_slide_fg.set_position(captcha_slide_bg.get_position() + mgl::vec2f(captcha_slide_padding_x, captcha_slide_padding_y)); if(has_captcha_bg) { captcha_slide_bg.draw(window); captcha_slide_fg.draw(window); } - captcha_solution_text.setPosition( - sf::Vector2f( - std::floor(window_size.x * 0.5f - captcha_solution_text.getLocalBounds().width * 0.5f), + captcha_solution_text.set_position( + mgl::vec2f( + std::floor(window_size.x * 0.5f - captcha_solution_text.get_bounds().size.x * 0.5f), std::floor(captcha_slide_bg.get_position().y + captcha_slide_bg.get_size().y + 10.0f))); window.draw(captcha_solution_text); } else if(navigation_stage == NavigationStage::VIEWING_ATTACHED_IMAGE) { - if(attached_image_texture->getNativeHandle() != 0) { + if(attached_image_texture->is_valid()) { if(image_control.moved) { - attached_image_sprite.setOrigin(floor(image_control.offset)); - attached_image_sprite.setScale(image_control.zoom, image_control.zoom); - attached_image_sprite.setPosition(floor(window_size * 0.5f)); + attached_image_sprite.set_origin(floor(image_control.offset)); + attached_image_sprite.set_scale(mgl::vec2f(image_control.zoom, image_control.zoom)); + attached_image_sprite.set_position(floor(window_size.to_vec2f() * 0.5f)); window.draw(attached_image_sprite); } else { - auto content_size = window_size; - sf::Vector2u texture_size = attached_image_texture->getSize(); - sf::Vector2f texture_size_f(texture_size.x, texture_size.y); + auto content_size = window_size.to_vec2f(); + mgl::vec2i texture_size = attached_image_texture->get_size(); + mgl::vec2f texture_size_f(texture_size.x, texture_size.y); auto image_scale = get_ratio(texture_size_f, clamp_to_size(texture_size_f, content_size)); image_control.zoom = std::min(image_scale.x, image_scale.y); - attached_image_sprite.setScale(image_scale); + attached_image_sprite.set_scale(image_scale); auto image_size = texture_size_f; image_size.x *= image_scale.x; image_size.y *= image_scale.y; - attached_image_sprite.setPosition(vec2f_floor(content_size.x * 0.5f - image_size.x * 0.5f, content_size.y * 0.5f - image_size.y * 0.5f)); + attached_image_sprite.set_position(vec2f_floor(content_size.x * 0.5f - image_size.x * 0.5f, content_size.y * 0.5f - image_size.y * 0.5f)); window.draw(attached_image_sprite); } } else { - sf::RectangleShape rect(sf::Vector2f(640.0f, 480.0f)); - rect.setFillColor(get_theme().image_loading_background_color); - auto content_size = window_size; - auto rect_size = clamp_to_size(rect.getSize(), content_size); - rect.setSize(rect_size); - rect.setPosition(vec2f_floor(content_size.x * 0.5f - rect_size.x * 0.5f, content_size.y * 0.5f - rect_size.y * 0.5f)); + mgl::Rectangle rect(mgl::vec2f(640.0f, 480.0f)); + rect.set_color(get_theme().image_loading_background_color); + auto content_size = window_size.to_vec2f(); + auto rect_size = clamp_to_size(rect.get_size(), content_size); + rect.set_size(rect_size); + rect.set_position(vec2f_floor(content_size.x * 0.5f - rect_size.x * 0.5f, content_size.y * 0.5f - rect_size.y * 0.5f)); window.draw(rect); - load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f); - load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0); + load_sprite.set_position(mgl::vec2f(window_size.x * 0.5f, window_size.y * 0.5f)); + load_sprite.set_rotation(load_sprite_timer.get_elapsed_time_seconds() * 400.0); window.draw(load_sprite); } } else if(navigation_stage == NavigationStage::REPLYING) { @@ -4535,16 +4500,16 @@ namespace QuickMedia { if((navigation_stage == NavigationStage::REPLYING || navigation_stage == NavigationStage::VIEWING_COMMENTS) && has_post_timeout) { int64_t time_left_until_post_again = seconds_until_post_again - (time(nullptr) - last_posted_time); if(time_left_until_post_again > 0) { - sf::RectangleShape time_left_bg(comment_input_shade.getSize()); - time_left_bg.setPosition(comment_input_shade.getPosition()); - time_left_bg.setFillColor(sf::Color(0, 0, 0, 100)); + mgl::Rectangle time_left_bg(comment_input_shade.get_size()); + time_left_bg.set_position(comment_input_shade.get_position()); + time_left_bg.set_color(mgl::Color(0, 0, 0, 100)); window.draw(time_left_bg); - sf::Text time_left_text("Wait " + std::to_string(time_left_until_post_again) + " second(s) before posting again", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(18 * get_config().scale * get_config().font_scale)); - time_left_text.setPosition(time_left_bg.getPosition() + - sf::Vector2f( - std::floor(time_left_bg.getSize().x * 0.5f - time_left_text.getLocalBounds().width * 0.5f), - std::floor(time_left_bg.getSize().y * 0.5f - time_left_text.getLocalBounds().height * 0.5f))); + mgl::Text time_left_text("Wait " + std::to_string(time_left_until_post_again) + " second(s) before posting again", *FontLoader::get_font(FontLoader::FontType::LATIN, 18 * get_config().scale * get_config().font_scale)); + time_left_text.set_position(time_left_bg.get_position() + + mgl::vec2f( + std::floor(time_left_bg.get_size().x * 0.5f - time_left_text.get_bounds().size.x * 0.5f), + std::floor(time_left_bg.get_size().y * 0.5f - time_left_text.get_bounds().size.y * 0.5f))); window.draw(time_left_text); } } @@ -4565,9 +4530,9 @@ namespace QuickMedia { SearchBar *inputs[num_inputs] = { &login_input, &password_input, &homeserver_input }; int focused_input = 0; - RoundedRectangle background(sf::Vector2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().shade_color, &rounded_rectangle_shader); + RoundedRectangle background(mgl::vec2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().shade_color, &rounded_rectangle_shader); - auto text_submit_callback = [this, inputs](const sf::String&) { + auto text_submit_callback = [this, inputs](const std::string&) { for(int i = 0; i < num_inputs; ++i) { if(inputs[i]->get_text().empty()) { show_notification("QuickMedia", "All fields need to be filled in", Urgency::CRITICAL); @@ -4603,26 +4568,24 @@ namespace QuickMedia { const float padding_y = std::floor(20.0f * get_config().scale); const float spacing_y = std::floor(20.0f * get_config().scale); - sf::Vector2f body_pos; - sf::Vector2f body_size; + mgl::vec2f body_pos; + mgl::vec2f body_size; bool redraw = true; - sf::Event event; + mgl::Event event; - while (current_page == PageType::CHAT_LOGIN && window.isOpen()) { - while (window.pollEvent(event)) { + while (current_page == PageType::CHAT_LOGIN && window.is_open()) { + while (window.poll_event(event)) { common_event_handler(event); event_idle_handler(event); - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); redraw = true; idle_active_handler(); - } else if(event.type == sf::Event::GainedFocus) { + } else if(event.type == mgl::Event::GainedFocus) { redraw = true; - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Tab) { + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Tab) { for(int i = 0; i < num_inputs; ++i) { inputs[i]->caret_visible = false; } @@ -4630,7 +4593,7 @@ namespace QuickMedia { inputs[focused_input]->caret_visible = true; idle_active_handler(); } - inputs[focused_input]->on_event(event); + inputs[focused_input]->on_event(window, event); } update_idle_state(); handle_x11_events(); @@ -4641,12 +4604,12 @@ namespace QuickMedia { if(redraw) { redraw = false; get_body_dimensions(window_size, nullptr, body_pos, body_size); - background.set_size(sf::Vector2f( - std::min(window_size.x, std::max(640.0f, window_size.x * 0.5f)), + background.set_size(mgl::vec2f( + std::min((float)window_size.x, std::max(640.0f, window_size.x * 0.5f)), num_inputs * inputs[0]->getBottomWithoutShadow() + padding_y * 2.0f + spacing_y * std::max(0, num_inputs - 1))); - background.set_position(window_size * 0.5f - background.get_size() * 0.5f); + background.set_position(window_size.to_vec2f() * 0.5f - background.get_size() * 0.5f); - sf::Vector2f pos = background.get_position() + sf::Vector2f(padding_x, padding_y); + mgl::vec2f pos = background.get_position() + mgl::vec2f(padding_x, padding_y); for(int i = 0; i < num_inputs; ++i) { inputs[i]->set_position(pos); pos.y += inputs[i]->getBottomWithoutShadow() + spacing_y; @@ -4657,7 +4620,7 @@ namespace QuickMedia { background.draw(window); for(int i = 0; i < num_inputs; ++i) { inputs[i]->update(); - inputs[i]->draw(window, background.get_size() - sf::Vector2f(padding_x * 2.0f, 0.0f), false); + inputs[i]->draw(window, background.get_size() - mgl::vec2f(padding_x * 2.0f, 0.0f), false); } AsyncImageLoader::get_instance().update(); window.display(); @@ -4669,7 +4632,7 @@ namespace QuickMedia { AsyncTask future; }; - static const sf::Vector2i CHAT_MESSAGE_THUMBNAIL_MAX_SIZE(600, 337); + static const mgl::vec2i CHAT_MESSAGE_THUMBNAIL_MAX_SIZE(600, 337); // TODO: Optimize static std::shared_ptr find_body_item_by_event_id(const std::shared_ptr *body_items, size_t num_body_items, const std::string &event_id, size_t *index_result = nullptr) { @@ -4852,7 +4815,7 @@ namespace QuickMedia { show_notification("QuickMedia", "Bug: current room empty", Urgency::CRITICAL); abort(); } - window.setTitle("QuickMedia - matrix - " + current_room->get_name()); + window.set_title(("QuickMedia - matrix - " + current_room->get_name()).c_str()); auto video_page = std::make_unique(this); bool move_room = false; @@ -4881,7 +4844,7 @@ namespace QuickMedia { tab.body->show_drop_shadow = false; } - Tabs ui_tabs(&rounded_rectangle_shader, is_touch_enabled() ? sf::Color::Transparent : get_theme().background_color); + Tabs ui_tabs(&rounded_rectangle_shader, is_touch_enabled() ? mgl::Color(0, 0, 0, 0) : get_theme().background_color); const int PINNED_TAB_INDEX = ui_tabs.add_tab("Pinned messages (0)", tabs[0].body.get()); const int MESSAGES_TAB_INDEX = ui_tabs.add_tab("Messages", tabs[1].body.get()); const int USERS_TAB_INDEX = ui_tabs.add_tab("Users (0)", tabs[2].body.get()); @@ -4894,14 +4857,13 @@ namespace QuickMedia { bool redraw = true; - sf::Clock read_marker_timer; - const sf::Int32 read_marker_timeout_ms_default = 3000; - sf::Int32 read_marker_timeout_ms = 0; + mgl::Clock read_marker_timer; + double read_marker_timeout_sec = 0; AsyncTask set_read_marker_future; bool setting_read_marker = false; - sf::Clock start_typing_timer; + mgl::Clock start_typing_timer; const double typing_timeout_seconds = 5.0; bool typing = false; @@ -4936,7 +4898,7 @@ namespace QuickMedia { } }; - bool is_window_focused = window.hasFocus(); + bool is_window_focused = window.has_focus(); enum class ChatState { NAVIGATING, @@ -4950,26 +4912,26 @@ namespace QuickMedia { ChatState chat_state = ChatState::NAVIGATING; std::shared_ptr currently_operating_on_item; - sf::Text replying_to_text("Replying to:", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(18 * get_config().scale * get_config().font_scale)); + mgl::Text replying_to_text("Replying to:", *FontLoader::get_font(FontLoader::FontType::LATIN, 18 * get_config().scale * get_config().font_scale)); - sf::Sprite logo_sprite(plugin_logo); - logo_sprite.setScale(0.8f * get_config().scale, 0.8f * get_config().scale); - sf::Vector2f logo_size(plugin_logo.getSize().x * logo_sprite.getScale().x, plugin_logo.getSize().y * logo_sprite.getScale().y); + mgl::Sprite logo_sprite(&plugin_logo); + logo_sprite.set_scale(mgl::vec2f(0.8f * get_config().scale, 0.8f * get_config().scale)); + mgl::vec2f logo_size(plugin_logo.get_size().x * logo_sprite.get_scale().x, plugin_logo.get_size().y * logo_sprite.get_scale().y); const float room_name_text_height = std::floor(18.0f * get_config().scale * get_config().font_scale); - sf::Text room_name_text("", *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD), room_name_text_height); + mgl::Text room_name_text("", *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD, room_name_text_height)); const float room_name_text_padding_y = std::floor(10.0f * get_config().scale); const float room_name_total_height = room_name_text_height + room_name_text_padding_y * 2.0f; const float room_avatar_height = 32.0f; const float room_topic_text_height = std::floor(12.0f * get_config().scale * get_config().font_scale); - sf::Text room_topic_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), room_topic_text_height); - room_topic_text.setFillColor(get_theme().faded_text_color); + mgl::Text room_topic_text("", *FontLoader::get_font(FontLoader::FontType::LATIN, room_topic_text_height)); + room_topic_text.set_color(get_theme().faded_text_color); - sf::Text room_label(matrix_chat_page->rooms_page->get_title(), *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD), std::floor(18 * get_config().scale * get_config().font_scale)); - room_label.setPosition(15.0f, room_name_text_padding_y + 4.0f); + mgl::Text room_label(matrix_chat_page->rooms_page->get_title(), *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD, 18 * get_config().scale * get_config().font_scale)); + room_label.set_position(mgl::vec2f(15.0f, room_name_text_padding_y + 4.0f)); - sf::Sprite room_avatar_sprite; + mgl::Sprite room_avatar_sprite; auto room_avatar_thumbnail_data = std::make_shared(); bool draw_room_list = show_room_side_panel; @@ -5205,10 +5167,10 @@ namespace QuickMedia { std::string room_topic = current_room->get_topic(); string_replace_all(room_name, '\n', ' '); string_replace_all(room_topic, '\n', ' '); - room_name_text.setString(sf::String::fromUtf8(room_name.begin(), room_name.end())); - room_topic_text.setString(sf::String::fromUtf8(room_topic.begin(), room_topic.end())); + room_name_text.set_string(std::move(room_name)); + room_topic_text.set_string(std::move(room_topic)); - read_marker_timeout_ms = 0; + read_marker_timeout_sec = 0; redraw = true; Entry chat_input("Press i to begin writing a message...", &rounded_rectangle_shader); @@ -5284,10 +5246,10 @@ namespace QuickMedia { }; struct Mention { - sf::Clock filter_timer; + mgl::Clock filter_timer; bool visible = false; bool filter_updated = false; - sf::String filter; + std::string filter; Body *users_tab_body = nullptr; void show() { @@ -5303,44 +5265,42 @@ namespace QuickMedia { users_tab_body->clear_cache(); } - void handle_event(const sf::Event &event) { + void handle_event(const mgl::Event &event) { if(visible) { - if(event.type == sf::Event::TextEntered) { + if(event.type == mgl::Event::TextEntered) { filter_timer.restart(); - if(event.text.unicode > 32) { - filter += event.text.unicode; + if(event.text.codepoint > 32) { + filter.append(event.text.str, event.text.size); filter_updated = true; - } else if(event.text.unicode == ' ' || event.text.unicode == '\t') { + } else if(event.text.codepoint == ' ' || event.text.codepoint == '\t') { hide(); } - } else if(event.type == sf::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::Up || (event.key.control && event.key.code == sf::Keyboard::K)) { + } else if(event.type == mgl::Event::KeyPressed) { + if(event.key.code == mgl::Keyboard::Up || (event.key.control && event.key.code == mgl::Keyboard::K)) { users_tab_body->select_previous_item(true); - } else if(event.key.code == sf::Keyboard::Down || (event.key.control && event.key.code == sf::Keyboard::J)) { + } else if(event.key.code == mgl::Keyboard::Down || (event.key.control && event.key.code == mgl::Keyboard::J)) { users_tab_body->select_next_item(true); - } else if(event.key.code == sf::Keyboard::Enter && event.key.shift) { + } else if(event.key.code == mgl::Keyboard::Enter && event.key.shift) { hide(); - } else if(event.key.code == sf::Keyboard::Backspace) { - if(filter.getSize() == 0) { + } else if(event.key.code == mgl::Keyboard::Backspace) { + if(filter.empty()) { hide(); } else { - filter.erase(filter.getSize() - 1, 1); + filter.erase(filter.size() - 1, 1); filter_updated = true; } } } } - if(event.type == sf::Event::TextEntered && event.text.unicode == '@' && !visible) + if(event.type == mgl::Event::TextEntered && event.text.codepoint == '@' && !visible) show(); } void update() { - if(visible && filter_updated && filter_timer.getElapsedTime().asMilliseconds() > 50) { + if(visible && filter_updated && filter_timer.get_elapsed_time_seconds() > 0.05) { filter_updated = false; - // TODO: Use std::string instead of sf::String - auto u8 = filter.toUtf8(); - users_tab_body->filter_search_fuzzy(*(std::string*)&u8); + users_tab_body->filter_search_fuzzy(filter); users_tab_body->select_first_item(); } } @@ -5360,7 +5320,7 @@ namespace QuickMedia { if(!str_to_append.empty()) str_to_append.erase(0, 1); str_to_append += " "; - chat_input.replace(chat_input.get_caret_index() - mention.filter.getSize(), mention.filter.getSize(), sf::String::fromUtf8(str_to_append.begin(), str_to_append.end())); + chat_input.replace(chat_input.get_caret_index() - mention.filter.size(), mention.filter.size(), str_to_append); mention.hide(); } return false; @@ -5690,12 +5650,12 @@ namespace QuickMedia { return false; }; - sf::Vector2f body_pos; - sf::Vector2f body_size; - sf::Event event; + mgl::vec2f body_pos; + mgl::vec2f body_size; + mgl::Event event; const float gradient_height = 5.0f; - sf::Vertex gradient_points[4]; + mgl::Vertex gradient_points[4]; double gradient_inc = 0; std::string before_token; @@ -5704,15 +5664,15 @@ namespace QuickMedia { bool fetched_enough_messages_bottom = false; bool has_unread_messages = false; - sf::RectangleShape more_messages_below_rect; - more_messages_below_rect.setFillColor(get_theme().new_items_alert_color); + mgl::Rectangle more_messages_below_rect; + more_messages_below_rect.set_color(get_theme().new_items_alert_color); - sf::RectangleShape chat_input_shade; - chat_input_shade.setFillColor(get_theme().shade_color); + mgl::Rectangle chat_input_shade; + chat_input_shade.set_color(get_theme().shade_color); float tab_vertical_offset = 0.0f; - sf::Clock frame_timer; + mgl::Clock frame_timer; float prev_chat_height = chat_input.get_height(); float chat_input_height_full = 0.0f; @@ -6103,9 +6063,9 @@ namespace QuickMedia { goto chat_page_end; } - while (current_page == PageType::CHAT && window.isOpen() && !move_room) { - sf::Int32 frame_time_ms = frame_timer.restart().asMilliseconds(); - while (window.pollEvent(event)) { + while (current_page == PageType::CHAT && window.is_open() && !move_room) { + int32_t frame_time_ms = frame_timer.restart() * 1000.0; + while (window.poll_event(event)) { common_event_handler(event); const int selected_tab = ui_tabs.get_selected(); @@ -6123,8 +6083,8 @@ namespace QuickMedia { base_event_handler(event, PageType::EXIT, tabs[selected_tab].body.get(), nullptr, false, false); event_idle_handler(event); if(!frame_skip_text_entry) { - if(!mention.visible || event.type != sf::Event::KeyPressed || (event.key.code != sf::Keyboard::Up && event.key.code != sf::Keyboard::Down && event.key.code != sf::Keyboard::Left && event.key.code != sf::Keyboard::Right)) - chat_input.process_event(event); + if(!mention.visible || event.type != mgl::Event::KeyPressed || (event.key.code != mgl::Keyboard::Up && event.key.code != mgl::Keyboard::Down && event.key.code != mgl::Keyboard::Left && event.key.code != mgl::Keyboard::Right)) + chat_input.process_event(window, event); if(chat_input.is_editable()) mention.handle_event(event); } @@ -6134,52 +6094,50 @@ namespace QuickMedia { idle_active_handler(); } - if(event.type == sf::Event::KeyPressed && event.key.alt && (chat_state == ChatState::NAVIGATING || chat_state == ChatState::URL_SELECTION)) { - if(event.key.code == sf::Keyboard::Up || (event.key.control && event.key.code == sf::Keyboard::K)) { + if(event.type == mgl::Event::KeyPressed && event.key.alt && (chat_state == ChatState::NAVIGATING || chat_state == ChatState::URL_SELECTION)) { + if(event.key.code == mgl::Keyboard::Up || (event.key.control && event.key.code == mgl::Keyboard::K)) { matrix_chat_page->rooms_page->body->select_previous_item(true); move_room = true; goto chat_page_end; - } else if(event.key.code == sf::Keyboard::Down || (event.key.control && event.key.code == sf::Keyboard::J)) { + } else if(event.key.code == mgl::Keyboard::Down || (event.key.control && event.key.code == mgl::Keyboard::J)) { matrix_chat_page->rooms_page->body->select_next_item(true); move_room = true; goto chat_page_end; - } else if(event.key.code == sf::Keyboard::PageUp) { + } else if(event.key.code == mgl::Keyboard::PageUp) { matrix_chat_page->rooms_page->body->select_previous_page(); move_room = true; goto chat_page_end; - } else if(event.key.code == sf::Keyboard::PageDown) { + } else if(event.key.code == mgl::Keyboard::PageDown) { matrix_chat_page->rooms_page->body->select_next_page(); move_room = true; goto chat_page_end; - } else if(event.key.code == sf::Keyboard::Home) { + } else if(event.key.code == mgl::Keyboard::Home) { matrix_chat_page->rooms_page->body->select_first_item(false); move_room = true; goto chat_page_end; - } else if(event.key.code == sf::Keyboard::End) { + } else if(event.key.code == mgl::Keyboard::End) { matrix_chat_page->rooms_page->body->select_last_item(); move_room = true; goto chat_page_end; - } else if(event.key.code == sf::Keyboard::Escape) { + } else if(event.key.code == mgl::Keyboard::Escape) { move_room = false; goto chat_page_end; } continue; } - if(event.type == sf::Event::GainedFocus) { + if(event.type == mgl::Event::GainedFocus) { is_window_focused = true; redraw = true; - } else if(event.type == sf::Event::LostFocus) { + } else if(event.type == mgl::Event::LostFocus) { is_window_focused = false; - } else if(event.type == sf::Event::Resized) { + } else if(event.type == mgl::Event::Resized) { redraw = true; idle_active_handler(); - } else if(event.type == sf::Event::GainedFocus) { - redraw = true; - } else if(event.type == sf::Event::KeyPressed && chat_state == ChatState::NAVIGATING) { - if(event.key.code == sf::Keyboard::Escape) { + } else if(event.type == mgl::Event::KeyPressed && chat_state == ChatState::NAVIGATING) { + if(event.key.code == mgl::Keyboard::Escape) { goto chat_page_end; - } else if(event.key.code == sf::Keyboard::I && event.key.control) { + } else if(event.key.code == mgl::Keyboard::I && event.key.control) { BodyItem *selected_item = tabs[selected_tab].body->get_selected(); if(selected_item && selected_item->url.empty()) selected_item = selected_item->embedded_item.get(); @@ -6206,13 +6164,13 @@ namespace QuickMedia { } if((selected_tab == MESSAGES_TAB_INDEX || selected_tab == PINNED_TAB_INDEX) && !frame_skip_text_entry) { - if(event.key.code == sf::Keyboard::Enter) { + if(event.key.code == mgl::Keyboard::Enter) { BodyItem *selected = tabs[selected_tab].body->get_selected(); if(selected) { if(!display_url_or_image(selected)) display_url_or_image(selected->embedded_item.get()); } - } else if(event.key.code == sf::Keyboard::S && event.key.control) { + } else if(event.key.code == mgl::Keyboard::S && event.key.control) { BodyItem *selected = tabs[selected_tab].body->get_selected(); if(selected) { if(!download_selected_item(selected)) @@ -6221,35 +6179,32 @@ namespace QuickMedia { } } - if(event.key.control && event.key.code == sf::Keyboard::C) { + if(event.key.control && event.key.code == mgl::Keyboard::C) { BodyItem *selected = tabs[selected_tab].body->get_selected(); - if(selected) { - auto desc = selected->get_description(); - sf::Clipboard::setString(sf::String::fromUtf8(desc.begin(), desc.end())); - } + if(selected) + set_clipboard(selected->get_description()); } if(selected_tab == MESSAGES_TAB_INDEX) { - if(event.key.code == sf::Keyboard::U) { + if(event.key.code == mgl::Keyboard::U) { frame_skip_text_entry = true; new_page = PageType::FILE_MANAGER; chat_input.set_editable(false); } - if(event.key.code == sf::Keyboard::I && !event.key.control) { + if(event.key.code == mgl::Keyboard::I && !event.key.control) { frame_skip_text_entry = true; chat_input.set_editable(true); chat_state = ChatState::TYPING_MESSAGE; } - if(event.key.control && event.key.code == sf::Keyboard::V) { + if(event.key.control && event.key.code == mgl::Keyboard::V) { frame_skip_text_entry = true; // TODO: Upload multiple files. - auto clipboard = sf::Clipboard::getString().toUtf8(); - upload_file(std::string(clipboard.begin(), clipboard.end())); + upload_file(window.get_clipboard()); } - if(event.key.code == sf::Keyboard::R && tabs[selected_tab].body->get_selected_shared()) { + if(event.key.code == mgl::Keyboard::R && tabs[selected_tab].body->get_selected_shared()) { std::shared_ptr selected = tabs[selected_tab].body->get_selected_shared(); Message *selected_message = static_cast(selected->userdata); const bool go_to_replied_message = event.key.control; @@ -6272,20 +6227,20 @@ namespace QuickMedia { chat_state = ChatState::REPLYING; currently_operating_on_item = selected; chat_input.set_editable(true); - replying_to_text.setString("Replying to:"); + replying_to_text.set_string("Replying to:"); frame_skip_text_entry = true; } } } } - if(event.key.code == sf::Keyboard::B && event.key.control) { + if(event.key.code == mgl::Keyboard::B && event.key.control) { // Reload room, goes to latest message l0l move_room = true; goto chat_page_end; } - if(event.key.code == sf::Keyboard::E) { + if(event.key.code == mgl::Keyboard::E) { frame_skip_text_entry = true; std::shared_ptr selected = tabs[selected_tab].body->get_selected_shared(); if(selected) { @@ -6305,7 +6260,7 @@ namespace QuickMedia { chat_input.set_editable(true); chat_input.set_text(selected->get_description()); // TODO: Description? it may change in the future, in which case this should be edited chat_input.move_caret_to_end(); - replying_to_text.setString("Editing message:"); + replying_to_text.set_string("Editing message:"); } } } else { @@ -6314,7 +6269,7 @@ namespace QuickMedia { } } - if(event.key.control && event.key.code == sf::Keyboard::D && !chat_input.is_editable()) { + if(event.key.control && event.key.code == mgl::Keyboard::D && !chat_input.is_editable()) { frame_skip_text_entry = true; BodyItem *selected = tabs[selected_tab].body->get_selected(); if(selected) { @@ -6342,7 +6297,7 @@ namespace QuickMedia { } } - if(event.key.control && event.key.code == sf::Keyboard::P && !chat_input.is_editable()) { + if(event.key.control && event.key.code == mgl::Keyboard::P && !chat_input.is_editable()) { frame_skip_text_entry = true; BodyItem *selected = tabs[selected_tab].body->get_selected(); if(selected) { @@ -6363,7 +6318,7 @@ namespace QuickMedia { } } } else if(selected_tab == PINNED_TAB_INDEX) { - if(event.key.control && event.key.code == sf::Keyboard::D && !chat_input.is_editable()) { + if(event.key.control && event.key.code == mgl::Keyboard::D && !chat_input.is_editable()) { frame_skip_text_entry = true; BodyItem *selected = tabs[selected_tab].body->get_selected(); if(selected) { @@ -6379,7 +6334,7 @@ namespace QuickMedia { } } - if(event.key.code == sf::Keyboard::R && event.key.control && tabs[selected_tab].body->get_selected_shared()) { + if(event.key.code == mgl::Keyboard::R && event.key.control && tabs[selected_tab].body->get_selected_shared()) { std::shared_ptr selected = tabs[selected_tab].body->get_selected_shared(); PinnedEventData *selected_event_data = static_cast(selected->userdata); if(selected_event_data && !selected_event_data->event_id.empty()) { @@ -6388,11 +6343,11 @@ namespace QuickMedia { } } } - } else if(event.type == sf::Event::KeyPressed && chat_state == ChatState::URL_SELECTION) { - if(event.key.code == sf::Keyboard::Escape) { + } else if(event.type == mgl::Event::KeyPressed && chat_state == ChatState::URL_SELECTION) { + if(event.key.code == mgl::Keyboard::Escape) { url_selection_body.clear_items(); chat_state = ChatState::NAVIGATING; - } else if(event.key.code == sf::Keyboard::Enter) { + } else if(event.key.code == mgl::Keyboard::Enter) { BodyItem *selected_item = url_selection_body.get_selected(); if(!selected_item) continue; @@ -6402,9 +6357,9 @@ namespace QuickMedia { if((chat_state == ChatState::TYPING_MESSAGE || chat_state == ChatState::REPLYING || chat_state == ChatState::EDITING) && selected_tab == MESSAGES_TAB_INDEX && !frame_skip_text_entry) { frame_skip_text_entry = false; - if(event.type == sf::Event::TextEntered) { + if(event.type == mgl::Event::TextEntered) { // TODO: Also show typing event when ctrl+v pasting? - if(event.text.unicode != 13) { // Return key + if(event.text.codepoint != 13) { // Return key start_typing_timer.restart(); if(!typing && current_room) { fprintf(stderr, "Started typing\n"); @@ -6412,7 +6367,7 @@ namespace QuickMedia { } typing = true; } - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) { + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Escape) { if(mention.visible) { mention.hide(); } else { @@ -6504,7 +6459,7 @@ namespace QuickMedia { // TODO: Instead of doing this, exit this current function and navigate to chat login page instead. //delete current_plugin; //current_plugin = new Matrix(); - window.setTitle("QuickMedia - matrix"); + window.set_title("QuickMedia - matrix"); current_page = PageType::CHAT_LOGIN; chat_login_page(); if(current_page == PageType::CHAT) @@ -6531,7 +6486,7 @@ namespace QuickMedia { break; } - if(typing && start_typing_timer.getElapsedTime().asSeconds() >= typing_timeout_seconds && current_room) { + if(typing && start_typing_timer.get_elapsed_time_seconds() >= typing_timeout_seconds && current_room) { fprintf(stderr, "Stopped typing\n"); typing = false; typing_state_queue.push(false); @@ -6540,10 +6495,9 @@ namespace QuickMedia { if(!current_room->body_item->thumbnail_url.empty()) room_avatar_thumbnail_data = AsyncImageLoader::get_instance().get_thumbnail(current_room->body_item->thumbnail_url, false, AVATAR_THUMBNAIL_SIZE); - if(room_avatar_thumbnail_data->loading_state == LoadingState::FINISHED_LOADING && room_avatar_thumbnail_data->image->getSize().x > 0 && room_avatar_thumbnail_data->image->getSize().y > 0) { - if(!room_avatar_thumbnail_data->texture.loadFromImage(*room_avatar_thumbnail_data->image)) + if(room_avatar_thumbnail_data->loading_state == LoadingState::FINISHED_LOADING && room_avatar_thumbnail_data->image->get_size().x > 0 && room_avatar_thumbnail_data->image->get_size().y > 0) { + if(!room_avatar_thumbnail_data->texture.load_from_image(*room_avatar_thumbnail_data->image)) fprintf(stderr, "Warning: failed to load texture for room avatar\n"); - room_avatar_thumbnail_data->texture.setSmooth(true); //room_avatar_thumbnail_data->texture.generateMipmap(); room_avatar_thumbnail_data->image.reset(); room_avatar_thumbnail_data->loading_state = LoadingState::APPLIED_TO_TEXTURE; @@ -6552,13 +6506,13 @@ namespace QuickMedia { if(room_avatar_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE && !avatar_applied) { avatar_applied = true; - room_avatar_sprite.setTexture(room_avatar_thumbnail_data->texture, true); - auto texture_size = room_avatar_sprite.getTexture()->getSize(); + room_avatar_sprite.set_texture(&room_avatar_thumbnail_data->texture); + auto texture_size = room_avatar_sprite.get_texture()->get_size(); if(texture_size.x > 0 && texture_size.y > 0) { float width_ratio = (float)texture_size.x / (float)texture_size.y; float height_scale = room_avatar_height / (float)texture_size.y; float width_scale = height_scale * width_ratio; - room_avatar_sprite.setScale(width_scale * get_config().scale, height_scale * get_config().scale); + room_avatar_sprite.set_scale(mgl::vec2f(width_scale * get_config().scale, height_scale * get_config().scale)); } redraw = true; } @@ -6590,28 +6544,28 @@ namespace QuickMedia { const float body_width = window_size.x; - this->body_pos = sf::Vector2f(0.0f, tab_shade_height); + this->body_pos = mgl::vec2f(0.0f, tab_shade_height); if(window_size.x > 900.0f * get_config().scale * get_config().font_scale && show_room_side_panel) { this->body_size = vec2f_floor(300.0f * get_config().scale * get_config().font_scale, window_size.y - tab_shade_height); draw_room_list = true; } else { - this->body_size = sf::Vector2f(0.0f, 0.0f); + this->body_size = mgl::vec2f(0.0f, 0.0f); draw_room_list = false; } - body_pos = sf::Vector2f(this->body_pos.x + this->body_size.x, tab_shade_height); - body_size = sf::Vector2f(body_width - this->body_pos.x - this->body_size.x, window_size.y - chat_input_height_full - tab_shade_height); + body_pos = mgl::vec2f(this->body_pos.x + this->body_size.x, tab_shade_height); + body_size = mgl::vec2f(body_width - this->body_pos.x - this->body_size.x, window_size.y - chat_input_height_full - tab_shade_height); - chat_input_shade.setSize(sf::Vector2f(window_size.x - body_pos.x, chat_input_height_full)); - chat_input_shade.setPosition(body_pos.x, window_size.y - chat_input_shade.getSize().y); + chat_input_shade.set_size(mgl::vec2f(window_size.x - body_pos.x, chat_input_height_full)); + chat_input_shade.set_position(mgl::vec2f(body_pos.x, window_size.y - chat_input_shade.get_size().y)); chat_input.set_max_width(window_size.x - (logo_padding_x + logo_size.x + chat_input_padding_x + logo_padding_x + body_pos.x)); chat_input.set_position(vec2f_floor(body_pos.x + logo_padding_x + logo_size.x + chat_input_padding_x, window_size.y - chat_height - chat_input_padding_y)); - more_messages_below_rect.setSize(sf::Vector2f(chat_input_shade.getSize().x, gradient_height)); - more_messages_below_rect.setPosition(chat_input_shade.getPosition().x, std::floor(window_size.y - chat_input_height_full - gradient_height)); + more_messages_below_rect.set_size(mgl::vec2f(chat_input_shade.get_size().x, gradient_height)); + more_messages_below_rect.set_position(mgl::vec2f(chat_input_shade.get_position().x, std::floor(window_size.y - chat_input_height_full - gradient_height))); - logo_sprite.setPosition(body_pos.x + logo_padding_x, std::floor(window_size.y - chat_input_height_full * 0.5f - logo_size.y * 0.5f)); + logo_sprite.set_position(mgl::vec2f(body_pos.x + logo_padding_x, std::floor(window_size.y - chat_input_height_full * 0.5f - logo_size.y * 0.5f))); } sync_data.messages.clear(); @@ -6716,52 +6670,52 @@ namespace QuickMedia { } else { tabs[selected_tab].body->draw(window, body_pos, body_size); if(selected_tab == MESSAGES_TAB_INDEX && mention.visible && chat_state == ChatState::TYPING_MESSAGE) { - sf::RectangleShape user_mention_background(sf::Vector2f(body_size.x, user_mention_body_height)); - user_mention_background.setPosition(sf::Vector2f(body_pos.x, body_pos.y + body_size.y - user_mention_body_height)); - user_mention_background.setFillColor(get_theme().shade_color); + mgl::Rectangle user_mention_background(mgl::vec2f(body_size.x, user_mention_body_height)); + user_mention_background.set_position(mgl::vec2f(body_pos.x, body_pos.y + body_size.y - user_mention_body_height)); + user_mention_background.set_color(get_theme().shade_color); window.draw(user_mention_background); - tabs[USERS_TAB_INDEX].body->draw(window, user_mention_background.getPosition(), user_mention_background.getSize()); + tabs[USERS_TAB_INDEX].body->draw(window, user_mention_background.get_position(), user_mention_background.get_size()); } } - //tab_shade.setSize(sf::Vector2f(window_size.x, tab_shade_height)); + //tab_shade.set_size(mgl::vec2f(window_size.x, tab_shade_height)); //window.draw(tab_shade); if(selected_tab == MESSAGES_TAB_INDEX || selected_tab == PINNED_TAB_INDEX || selected_tab == USERS_TAB_INDEX) { float room_name_text_offset_x = std::floor(10.0f * get_config().scale); - if(room_avatar_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE && room_avatar_sprite.getTexture() && room_avatar_sprite.getTexture()->getNativeHandle() != 0) { - auto room_avatar_texture_size = room_avatar_sprite.getTexture()->getSize(); - room_avatar_texture_size.x *= room_avatar_sprite.getScale().x; - room_avatar_texture_size.y *= room_avatar_sprite.getScale().y; - room_avatar_sprite.setPosition(body_pos.x + std::floor(10.0f * get_config().scale), room_name_total_height * 0.5f - room_avatar_texture_size.y * 0.5f + 5.0f); - circle_mask_shader.setUniform("resolution", sf::Vector2f(room_avatar_texture_size.x, room_avatar_texture_size.y)); + if(room_avatar_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE && room_avatar_sprite.get_texture() && room_avatar_sprite.get_texture()->is_valid()) { + auto room_avatar_texture_size = room_avatar_sprite.get_texture()->get_size(); + room_avatar_texture_size.x *= room_avatar_sprite.get_scale().x; + room_avatar_texture_size.y *= room_avatar_sprite.get_scale().y; + room_avatar_sprite.set_position(mgl::vec2f(body_pos.x + std::floor(10.0f * get_config().scale), room_name_total_height * 0.5f - room_avatar_texture_size.y * 0.5f + 5.0f)); + circle_mask_shader.set_uniform("resolution", mgl::vec2f(room_avatar_texture_size.x, room_avatar_texture_size.y)); window.draw(room_avatar_sprite, &circle_mask_shader); room_name_text_offset_x += room_avatar_texture_size.x + 10.0f; } - room_name_text.setPosition(body_pos.x + room_name_text_offset_x, room_name_text_padding_y); + room_name_text.set_position(mgl::vec2f(body_pos.x + room_name_text_offset_x, room_name_text_padding_y - 3.0f)); window.draw(room_name_text); - room_topic_text.setPosition(room_name_text.getPosition().x + room_name_text.getLocalBounds().width + 15.0f, room_name_text_padding_y + 2.0f + room_name_text_height * 0.5f - room_topic_text_height * 0.5f); + room_topic_text.set_position(mgl::vec2f(room_name_text.get_position().x + room_name_text.get_bounds().size.x + 15.0f, room_name_text_padding_y - 1.0f + room_name_text_height * 0.5f - room_topic_text_height * 0.5f)); window.draw(room_topic_text); } if(draw_room_list) { - sf::RectangleShape room_list_background(sf::Vector2f(this->body_size.x, window_size.y)); - //room_list_background.setPosition(this->body_pos); - room_list_background.setFillColor(get_theme().shade_color); + mgl::Rectangle room_list_background(mgl::vec2f(this->body_size.x, window_size.y)); + //room_list_background.set_position(this->body_pos); + room_list_background.set_color(get_theme().shade_color); window.draw(room_list_background); window.draw(room_label); const float tab_y = std::floor(tab_vertical_offset) + room_name_padding_y; - matrix_chat_page->rooms_page->body->draw(window, sf::Vector2f(0.0f, tab_y), sf::Vector2f(this->body_size.x, window_size.y - tab_y), Json::Value::nullSingleton()); + matrix_chat_page->rooms_page->body->draw(window, mgl::vec2f(0.0f, tab_y), mgl::vec2f(this->body_size.x, window_size.y - tab_y), Json::Value::nullSingleton()); } - ui_tabs.draw(window, sf::Vector2f(body_pos.x, std::floor(tab_vertical_offset) + room_name_padding_y), body_size.x); + ui_tabs.draw(window, mgl::vec2f(body_pos.x, std::floor(tab_vertical_offset) + room_name_padding_y), body_size.x); if(chat_state == ChatState::REPLYING || chat_state == ChatState::EDITING) { const float margin = 5.0f; - const float replying_to_text_height = replying_to_text.getLocalBounds().height + margin; + const float replying_to_text_height = replying_to_text.get_bounds().size.y + margin; float item_height = std::min(body_size.y - replying_to_text_height - margin, tabs[MESSAGES_TAB_INDEX].body->get_item_height(currently_operating_on_item.get(), body_size.x) + margin); if(item_height < 0.0f) @@ -6771,38 +6725,38 @@ namespace QuickMedia { if(mention.visible) extra_user_mention_height = user_mention_body_height; - sf::RectangleShape overlay(sf::Vector2f(window_size.x, window_size.y - chat_input_height_full - extra_user_mention_height)); - overlay.setFillColor(sf::Color(0, 0, 0, 240)); + mgl::Rectangle overlay(mgl::vec2f(window_size.x, window_size.y - chat_input_height_full - extra_user_mention_height)); + overlay.set_color(mgl::Color(0, 0, 0, 240)); window.draw(overlay); const float padding_x = std::floor(10.0f * get_config().scale); - sf::Vector2f body_item_pos(body_pos.x + padding_x, window_size.y - chat_input_height_full - item_height); - sf::Vector2f body_item_size(body_size.x - padding_x * 2.0f, item_height); + mgl::vec2f body_item_pos(body_pos.x + padding_x, window_size.y - chat_input_height_full - item_height); + mgl::vec2f body_item_size(body_size.x - padding_x * 2.0f, item_height); - sf::RectangleShape item_background(sf::Vector2f(window_size.x, body_item_size.y + chat_input_height_full + replying_to_text_height + margin)); - item_background.setPosition(sf::Vector2f(0.0f, window_size.y - (body_item_size.y + chat_input_height_full + replying_to_text_height + margin))); - item_background.setFillColor(get_theme().background_color); + mgl::Rectangle item_background(mgl::vec2f(window_size.x, body_item_size.y + chat_input_height_full + replying_to_text_height + margin)); + item_background.set_position(mgl::vec2f(0.0f, window_size.y - (body_item_size.y + chat_input_height_full + replying_to_text_height + margin))); + item_background.set_color(get_theme().background_color); window.draw(item_background); if(mention.visible) { - sf::RectangleShape user_mention_background(sf::Vector2f(window_size.x, user_mention_body_height)); - user_mention_background.setPosition(sf::Vector2f(0.0f, item_background.getPosition().y - user_mention_body_height)); - user_mention_background.setFillColor(get_theme().shade_color); + mgl::Rectangle user_mention_background(mgl::vec2f(window_size.x, user_mention_body_height)); + user_mention_background.set_position(mgl::vec2f(0.0f, item_background.get_position().y - user_mention_body_height)); + user_mention_background.set_color(get_theme().shade_color); window.draw(user_mention_background); tabs[USERS_TAB_INDEX].body->draw(window, - sf::Vector2f(body_pos.x + padding_x, item_background.getPosition().y - user_mention_body_height), - sf::Vector2f(body_size.x - padding_x * 2.0f, user_mention_body_height)); + mgl::vec2f(body_pos.x + padding_x, item_background.get_position().y - user_mention_body_height), + mgl::vec2f(body_size.x - padding_x * 2.0f, user_mention_body_height)); } - replying_to_text.setPosition(body_item_pos.x, body_item_pos.y - replying_to_text_height); + replying_to_text.set_position(mgl::vec2f(body_item_pos.x, body_item_pos.y - replying_to_text_height)); window.draw(replying_to_text); tabs[MESSAGES_TAB_INDEX].body->draw_item(window, currently_operating_on_item, body_item_pos, body_item_size); } if(selected_tab == MESSAGES_TAB_INDEX && current_room && current_room->body_item && (!current_room->last_message_read || has_unread_messages) && matrix->is_initial_sync_finished()) { - if(after_token.empty() && !tabs[selected_tab].body->is_bottom_cut_off() && is_window_focused && chat_state != ChatState::URL_SELECTION && !setting_read_marker && read_marker_timer.getElapsedTime().asMilliseconds() >= read_marker_timeout_ms) { + if(after_token.empty() && !tabs[selected_tab].body->is_bottom_cut_off() && is_window_focused && chat_state != ChatState::URL_SELECTION && !setting_read_marker && read_marker_timer.get_elapsed_time_seconds() >= read_marker_timeout_sec) { auto body_items = tabs[selected_tab].body->get_items(); int last_timeline_message = (int)body_items.size() - 1; for(int i = last_timeline_message - 1; i >= 0; --i) { @@ -6860,9 +6814,9 @@ namespace QuickMedia { // TODO: fetch_messages_dir double progress = 0.5 + std::sin(std::fmod(gradient_inc, 360.0) * 0.017453292519943295 - 1.5707963267948966*0.5) * 0.5; gradient_inc += (frame_time_ms * 0.5); - sf::Color top_color = interpolate_colors(get_theme().background_color, get_theme().loading_page_color, progress); + mgl::Color top_color = interpolate_colors(get_theme().background_color, get_theme().loading_page_color, progress); - gradient_points[0].position.x = chat_input_shade.getPosition().x; + gradient_points[0].position.x = chat_input_shade.get_position().x; gradient_points[0].position.y = tab_shade_height; gradient_points[1].position.x = window_size.x; @@ -6871,7 +6825,7 @@ namespace QuickMedia { gradient_points[2].position.x = window_size.x; gradient_points[2].position.y = tab_shade_height + gradient_height; - gradient_points[3].position.x = chat_input_shade.getPosition().x; + gradient_points[3].position.x = chat_input_shade.get_position().x; gradient_points[3].position.y = tab_shade_height + gradient_height; gradient_points[0].color = top_color; @@ -6880,10 +6834,10 @@ namespace QuickMedia { gradient_points[3].color = get_theme().background_color; if(fetch_messages_dir == MessageDirection::AFTER) { - gradient_points[0].position.y = more_messages_below_rect.getPosition().y; - gradient_points[1].position.y = more_messages_below_rect.getPosition().y; - gradient_points[2].position.y = more_messages_below_rect.getPosition().y + gradient_height; - gradient_points[3].position.y = more_messages_below_rect.getPosition().y + gradient_height; + gradient_points[0].position.y = more_messages_below_rect.get_position().y; + gradient_points[1].position.y = more_messages_below_rect.get_position().y; + gradient_points[2].position.y = more_messages_below_rect.get_position().y + gradient_height; + gradient_points[3].position.y = more_messages_below_rect.get_position().y + gradient_height; gradient_points[0].color = get_theme().background_color; gradient_points[1].color = get_theme().background_color; @@ -6891,7 +6845,7 @@ namespace QuickMedia { gradient_points[3].color = top_color; } - window.draw(gradient_points, 4, sf::Quads); // Note: sf::Quads doesn't work with egl + window.draw(gradient_points, 4, mgl::PrimitiveType::Quads); // Note: mgl::PrimitiveType::Quads doesn't work with egl } if(selected_tab == MESSAGES_TAB_INDEX) { @@ -6999,7 +6953,7 @@ namespace QuickMedia { matrix_chat_page->set_current_room(nullptr, nullptr); fetch_messages_future.cancel(); cleanup_tasks(); - window.setTitle("QuickMedia - matrix"); + window.set_title("QuickMedia - matrix"); return move_room; } @@ -7012,7 +6966,7 @@ namespace QuickMedia { } void Program::after_matrix_login_page() { - if(!window.isOpen()) + if(!window.is_open()) exit(exit_code); auto rooms_tags_body = create_body(); @@ -7078,7 +7032,7 @@ namespace QuickMedia { } void Program::download_page(std::string url) { - window.setTitle("QuickMedia - Select where you want to save " + std::string(url)); + window.set_title(("QuickMedia - Select where you want to save " + std::string(url)).c_str()); url = invidious_url_to_youtube_url(url); const bool download_use_youtube_dl = url_should_download_with_youtube_dl(url); @@ -7225,32 +7179,18 @@ namespace QuickMedia { string_replace_all(filename, '/', '_'); std::string output_filepath = file_save_page(filename); - if(!window.isOpen() || output_filepath.empty()) { + if(!window.is_open() || output_filepath.empty()) { exit_code = 1; return; } - sf::Vector2i monitor_size; - sf::Vector2i focused_monitor_center = get_focused_monitor_center(disp, monitor_size); + mgl::vec2i monitor_size; + mgl::vec2i focused_monitor_center = get_focused_monitor_center(disp, monitor_size); window_size.x = std::min(monitor_size.x, (int)(300.0f + 380.0f * get_config().scale)); window_size.y = std::min(monitor_size.y, (int)(50.0f + 130.0f * get_config().scale)); - window.setSize(sf::Vector2u(window_size.x, window_size.y)); - XSizeHints *size_hints = XAllocSizeHints(); - if(size_hints) { - size_hints->width = window_size.x; - size_hints->min_width = window_size.x; - size_hints->max_width = window_size.x; - - size_hints->height = window_size.y; - size_hints->min_height = window_size.y; - size_hints->max_height = window_size.y; - size_hints->flags = PSize | PMinSize | PMaxSize; - - XSetWMNormalHints(disp, x11_window, size_hints); - XFree(size_hints); - XFlush(disp); - } - window.setPosition(sf::Vector2i(focused_monitor_center.x - window_size.x * 0.5f, focused_monitor_center.y - window_size.y * 0.5f)); + window.set_size(mgl::vec2i(window_size.x, window_size.y)); + window.set_size_limits(window_size, window_size); + window.set_position(mgl::vec2i(focused_monitor_center.x - window_size.x * 0.5f, focused_monitor_center.y - window_size.y * 0.5f)); std::string output_filepath_s = output_filepath; char *output_dir = dirname(output_filepath_s.data()); @@ -7266,22 +7206,22 @@ namespace QuickMedia { const float loading_bar_padding_x = std::floor(4.0f * get_config().scale); const float loading_bar_padding_y = std::floor(4.0f * get_config().scale); - RoundedRectangle loading_bar_background(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale), get_theme().background_color, &rounded_rectangle_shader); - RoundedRectangle loading_bar(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale - loading_bar_padding_y), get_theme().loading_bar_color, &rounded_rectangle_shader); + RoundedRectangle loading_bar_background(mgl::vec2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale), get_theme().background_color, &rounded_rectangle_shader); + RoundedRectangle loading_bar(mgl::vec2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale - loading_bar_padding_y), get_theme().loading_bar_color, &rounded_rectangle_shader); const float padding_x = std::floor(30.0f * get_config().scale); const float spacing_y = std::floor(15.0f * get_config().scale); const float loading_bar_height = std::floor(20.0f * get_config().scale); - sf::Text progress_text("0kb/Unknown", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(20.0f * get_config().scale * get_config().font_scale)); - sf::Text status_text("Downloading", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(20.0f * get_config().scale * get_config().font_scale)); - sf::Text filename_text(filename.c_str(), *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14.0f * get_config().scale * get_config().font_scale)); - filename_text.setFillColor(get_theme().faded_text_color); - sf::Text download_speed_text("0 bytes/s", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14.0f * get_config().scale * get_config().font_scale)); - download_speed_text.setFillColor(get_theme().faded_text_color); + mgl::Text progress_text("0kb/Unknown", *FontLoader::get_font(FontLoader::FontType::LATIN, 20.0f * get_config().scale * get_config().font_scale)); + mgl::Text status_text("Downloading", *FontLoader::get_font(FontLoader::FontType::LATIN, 20.0f * get_config().scale * get_config().font_scale)); + mgl::Text filename_text(filename.c_str(), *FontLoader::get_font(FontLoader::FontType::LATIN, 14.0f * get_config().scale * get_config().font_scale)); + filename_text.set_color(get_theme().faded_text_color); + mgl::Text download_speed_text("0 bytes/s", *FontLoader::get_font(FontLoader::FontType::LATIN, 14.0f * get_config().scale * get_config().font_scale)); + download_speed_text.set_color(get_theme().faded_text_color); bool redraw = true; - sf::Event event; + mgl::Event event; std::unique_ptr downloader; if(download_use_youtube_dl) { @@ -7306,20 +7246,18 @@ namespace QuickMedia { return; } - sf::Clock frame_timer; - sf::Clock progress_update_timer; + mgl::Clock frame_timer; + mgl::Clock progress_update_timer; bool download_completed = false; float progress = 0.0f; float ui_progress = 0.0f; - while(window.isOpen()) { - while (window.pollEvent(event)) { + while(window.is_open()) { + while (window.poll_event(event)) { common_event_handler(event); - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); redraw = true; } } @@ -7332,7 +7270,7 @@ namespace QuickMedia { exit(exit_code); } - if(progress_update_timer.getElapsedTime().asSeconds() >= 1.0f) { + if(progress_update_timer.get_elapsed_time_seconds() >= 1.0f) { progress_update_timer.restart(); DownloadUpdateStatus update_status = downloader->update(); switch(update_status) { @@ -7348,29 +7286,29 @@ namespace QuickMedia { progress = downloader->get_progress(); progress = std::max(0.0f, std::min(1.0f, progress)); - progress_text.setString(downloader->get_progress_text()); - download_speed_text.setString(downloader->get_download_speed_text()); + progress_text.set_string(downloader->get_progress_text()); + download_speed_text.set_string(downloader->get_download_speed_text()); redraw = true; } if(redraw) { redraw = false; - loading_bar_background.set_size(sf::Vector2f(window_size.x - padding_x * 2.0f, loading_bar_height)); - loading_bar_background.set_position(window_size * 0.5f - loading_bar_background.get_size() * 0.5f + sf::Vector2f(0.0f, download_speed_text.getLocalBounds().height * 0.5f)); + loading_bar_background.set_size(mgl::vec2f(window_size.x - padding_x * 2.0f, loading_bar_height)); + loading_bar_background.set_position(window_size.to_vec2f() * 0.5f - loading_bar_background.get_size() * 0.5f + mgl::vec2f(0.0f, download_speed_text.get_bounds().size.y * 0.5f)); loading_bar_background.set_position(vec2f_floor(loading_bar_background.get_position().x, loading_bar_background.get_position().y)); - loading_bar.set_position(loading_bar_background.get_position() + sf::Vector2f(loading_bar_padding_x, loading_bar_padding_y)); - filename_text.setPosition( - loading_bar_background.get_position() + sf::Vector2f(0.0f, -(filename_text.getLocalBounds().height + spacing_y))); - progress_text.setPosition( - filename_text.getPosition() + sf::Vector2f(loading_bar_background.get_size().x - progress_text.getLocalBounds().width, -(progress_text.getLocalBounds().height + spacing_y))); - status_text.setPosition( - filename_text.getPosition() + sf::Vector2f(0.0f, -(status_text.getLocalBounds().height + spacing_y))); - download_speed_text.setPosition( - loading_bar_background.get_position() + sf::Vector2f(0.0f, loading_bar_height + spacing_y)); + loading_bar.set_position(loading_bar_background.get_position() + mgl::vec2f(loading_bar_padding_x, loading_bar_padding_y)); + filename_text.set_position( + loading_bar_background.get_position() + mgl::vec2f(0.0f, -(filename_text.get_bounds().size.y + spacing_y))); + progress_text.set_position( + filename_text.get_position() + mgl::vec2f(loading_bar_background.get_size().x - progress_text.get_bounds().size.x, -(progress_text.get_bounds().size.y + spacing_y))); + status_text.set_position( + filename_text.get_position() + mgl::vec2f(0.0f, -(status_text.get_bounds().size.y + spacing_y))); + download_speed_text.set_position( + loading_bar_background.get_position() + mgl::vec2f(0.0f, loading_bar_height + spacing_y)); } const float progress_diff = progress - ui_progress; - const float progress_move = frame_timer.getElapsedTime().asSeconds() * 500.0f * std::abs(progress_diff); + const float progress_move = frame_timer.get_elapsed_time_seconds() * 500.0f * std::abs(progress_diff); if(std::abs(progress_diff) < progress_move) { ui_progress = progress; } else { @@ -7380,7 +7318,7 @@ namespace QuickMedia { ui_progress -= progress_move; } - loading_bar.set_size(sf::Vector2f( + loading_bar.set_size(mgl::vec2f( std::floor((loading_bar_background.get_size().x - loading_bar_padding_x * 2.0f) * ui_progress), loading_bar_height - loading_bar_padding_y * 2.0f)); @@ -7409,10 +7347,10 @@ namespace QuickMedia { } std::string Program::file_save_page(const std::string &filename) { - sf::Vector2f body_pos; - sf::Vector2f body_size; + mgl::vec2f body_pos; + mgl::vec2f body_size; bool redraw = true; - sf::Event event; + mgl::Event event; auto file_manager_page = std::make_unique(this); file_manager_page->set_current_directory(file_manager_start_dir); @@ -7431,8 +7369,8 @@ namespace QuickMedia { }; search_bar->onTextSubmitCallback = [this, &search_bar, &file_manager_body, &file_manager_page, &ui_tabs, tab_path_index](const std::string&) { - if(sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl)) - return; + if(window.is_key_pressed(mgl::Keyboard::LControl) || window.is_key_pressed(mgl::Keyboard::RControl)) + return; BodyItem *selected = file_manager_body->get_selected(); if(!selected) @@ -7459,28 +7397,27 @@ namespace QuickMedia { const float bottom_panel_padding = 10.0f; const float bottom_panel_spacing = 10.0f; - Button cancel_button("Cancel", FontLoader::get_font(FontLoader::FontType::LATIN), 16, 100.0f, &rounded_rectangle_shader, get_config().scale * get_config().font_scale); + Button cancel_button("Cancel", FontLoader::get_font(FontLoader::FontType::LATIN, 16 * get_config().scale), 100.0f, &rounded_rectangle_shader, get_config().scale * get_config().font_scale); cancel_button.set_background_color(get_theme().cancel_button_background_color); - Button save_button("Save", FontLoader::get_font(FontLoader::FontType::LATIN), 16, 100.0f, &rounded_rectangle_shader, get_config().scale * get_config().font_scale); + Button save_button("Save", FontLoader::get_font(FontLoader::FontType::LATIN, 16 * get_config().scale), 100.0f, &rounded_rectangle_shader, get_config().scale * get_config().font_scale); save_button.set_background_color(get_theme().confirm_button_background_color); - sf::Text file_name_label("File name:", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16.0f * get_config().scale * get_config().font_scale)); + mgl::Text file_name_label("File name:", *FontLoader::get_font(FontLoader::FontType::LATIN, 16.0f * get_config().scale * get_config().font_scale)); Entry file_name_entry("", &rounded_rectangle_shader); file_name_entry.set_text(filename); file_name_entry.set_single_line(true); file_name_entry.set_editable(false); - sf::RectangleShape bottom_panel_background; - bottom_panel_background.setFillColor(get_theme().shade_color); + mgl::Rectangle bottom_panel_background; + bottom_panel_background.set_color(get_theme().shade_color); const float gradient_height = 5.0f; - sf::Vertex gradient_points[4]; + mgl::Vertex gradient_points[4]; auto save_file = [this, &file_name_entry, &file_manager_page]() -> std::string { - auto u8 = file_name_entry.get_text().toUtf8(); - std::string *filename = (std::string*)&u8; + const std::string *filename = &file_name_entry.get_text(); Path filename_full_path = file_manager_page->get_current_directory().string(); filename_full_path.join(*filename); @@ -7520,15 +7457,15 @@ namespace QuickMedia { float prev_entry_height = file_name_entry.get_height(); - while (window.isOpen()) { - while (window.pollEvent(event)) { + while (window.is_open()) { + while (window.poll_event(event)) { common_event_handler(event); if(file_manager_body->on_event(window, event, !file_name_entry.is_editable())) idle_active_handler(); else event_idle_handler(event); - search_bar->on_event(event); + search_bar->on_event(window, event); if(cancel_button.on_event(event) & BUTTON_EVENT_CLICKED) return ""; if(save_button.on_event(event) & BUTTON_EVENT_CLICKED) { @@ -7536,25 +7473,23 @@ namespace QuickMedia { if(!save_path.empty()) return save_path; } - file_name_entry.process_event(event); + file_name_entry.process_event(window, event); - if(event.type == sf::Event::Resized) { + if(event.type == mgl::Event::Resized) { window_size.x = event.size.width; window_size.y = event.size.height; - sf::FloatRect visible_area(0, 0, window_size.x, window_size.y); - window.setView(sf::View(visible_area)); redraw = true; idle_active_handler(); - } else if(event.type == sf::Event::GainedFocus) { + } else if(event.type == mgl::Event::GainedFocus) { redraw = true; - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Tab) { + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Tab) { file_name_entry.set_editable(!file_name_entry.is_editable()); search_bar->set_editable(!search_bar->is_editable()); - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Enter && event.key.control) { + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Enter && event.key.control) { std::string save_path = save_file(); if(!save_path.empty()) return save_path; - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) { + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Escape) { window.close(); } } @@ -7573,30 +7508,30 @@ namespace QuickMedia { get_body_dimensions(window_size, search_bar.get(), body_pos, body_size); body_pos.y += Tabs::get_shade_height(); body_size.y -= Tabs::get_shade_height(); - save_button.set_position(window_size - sf::Vector2f(save_button.get_width(), save_button.get_height()) - sf::Vector2f(bottom_panel_padding, bottom_panel_padding)); - cancel_button.set_position(save_button.get_position() - sf::Vector2f(cancel_button.get_width() + bottom_panel_spacing, 0.0f)); - file_name_label.setPosition(sf::Vector2f(bottom_panel_spacing, std::floor(window_size.y - bottom_panel_padding - file_name_entry.get_height() * 0.5f - file_name_label.getLocalBounds().height * 0.5f - 5.0f * get_config().scale))); - file_name_entry.set_position(sf::Vector2f(file_name_label.getPosition().x + file_name_label.getLocalBounds().width + bottom_panel_spacing, window_size.y - file_name_entry.get_height() - bottom_panel_padding)); - file_name_entry.set_max_width(std::floor(cancel_button.get_position().x - bottom_panel_spacing - file_name_label.getLocalBounds().width - bottom_panel_spacing - bottom_panel_spacing)); - bottom_panel_background.setPosition(0.0f, window_size.y - std::floor(bottom_panel_padding * 2.0f + file_name_entry.get_height())); - bottom_panel_background.setSize(sf::Vector2f(window_size.x, std::floor(bottom_panel_padding * 2.0f + file_name_entry.get_height()))); + save_button.set_position(window_size.to_vec2f() - mgl::vec2f(save_button.get_width(), save_button.get_height()) - mgl::vec2f(bottom_panel_padding, bottom_panel_padding)); + cancel_button.set_position(save_button.get_position() - mgl::vec2f(cancel_button.get_width() + bottom_panel_spacing, 0.0f)); + file_name_label.set_position(mgl::vec2f(bottom_panel_spacing, std::floor(window_size.y - bottom_panel_padding - file_name_entry.get_height() * 0.5f - file_name_label.get_bounds().size.y * 0.5f - 5.0f * get_config().scale))); + file_name_entry.set_position(mgl::vec2f(file_name_label.get_position().x + file_name_label.get_bounds().size.x + bottom_panel_spacing, window_size.y - file_name_entry.get_height() - bottom_panel_padding)); + file_name_entry.set_max_width(std::floor(cancel_button.get_position().x - bottom_panel_spacing - file_name_label.get_bounds().size.x - bottom_panel_spacing - bottom_panel_spacing)); + bottom_panel_background.set_position(mgl::vec2f(0.0f, window_size.y - std::floor(bottom_panel_padding * 2.0f + file_name_entry.get_height()))); + bottom_panel_background.set_size(mgl::vec2f(window_size.x, std::floor(bottom_panel_padding * 2.0f + file_name_entry.get_height()))); - const sf::Color color(0, 0, 0, 50); - gradient_points[0] = sf::Vertex(bottom_panel_background.getPosition() + sf::Vector2f(0.0f, -gradient_height), sf::Color(color.r, color.g, color.b, 0)); - gradient_points[1] = sf::Vertex(bottom_panel_background.getPosition() + sf::Vector2f(bottom_panel_background.getSize().x, -gradient_height), sf::Color(color.r, color.g, color.b, 0)); - gradient_points[2] = sf::Vertex(bottom_panel_background.getPosition() + sf::Vector2f(bottom_panel_background.getSize().x, 0.0f), color); - gradient_points[3] = sf::Vertex(bottom_panel_background.getPosition() + sf::Vector2f(0.0f, 0.0f), color); + const mgl::Color color(0, 0, 0, 50); + gradient_points[0] = mgl::Vertex(bottom_panel_background.get_position() + mgl::vec2f(0.0f, -gradient_height), mgl::Color(color.r, color.g, color.b, 0)); + gradient_points[1] = mgl::Vertex(bottom_panel_background.get_position() + mgl::vec2f(bottom_panel_background.get_size().x, -gradient_height), mgl::Color(color.r, color.g, color.b, 0)); + gradient_points[2] = mgl::Vertex(bottom_panel_background.get_position() + mgl::vec2f(bottom_panel_background.get_size().x, 0.0f), color); + gradient_points[3] = mgl::Vertex(bottom_panel_background.get_position() + mgl::vec2f(0.0f, 0.0f), color); } window.clear(get_theme().background_color); - ui_tabs.draw(window, sf::Vector2f(0.0f, search_bar->getBottomWithoutShadow()), window_size.x); - search_bar->draw(window, window_size, true); + ui_tabs.draw(window, mgl::vec2f(0.0f, search_bar->getBottomWithoutShadow()), window_size.x); + search_bar->draw(window, window_size.to_vec2f(), true); - file_manager_body->draw(window, body_pos, body_size - sf::Vector2f(0.0f, bottom_panel_background.getSize().y)); + file_manager_body->draw(window, body_pos, body_size - mgl::vec2f(0.0f, bottom_panel_background.get_size().y)); window.draw(bottom_panel_background); - window.draw(gradient_points, 4, sf::Quads); + window.draw(gradient_points, 4, mgl::PrimitiveType::Quads); window.draw(file_name_label); cancel_button.draw(window); save_button.draw(window); diff --git a/src/ResourceLoader.cpp b/src/ResourceLoader.cpp index 2725898..89ae510 100644 --- a/src/ResourceLoader.cpp +++ b/src/ResourceLoader.cpp @@ -2,16 +2,19 @@ #include "../include/Program.hpp" #include "../include/Path.hpp" #include "../include/StringUtils.hpp" -#include -#include +#include +#include +#include #include #include #include #include static std::string resource_root; -static std::array, 4> font_cache; -static std::unordered_map> texture_cache; +static std::array, 4> font_file_cache; +// font_cache[(unsigned int)font_type][character_size] +static std::array>, 4> font_cache; +static std::unordered_map> texture_cache; static bool use_system_fonts = false; namespace QuickMedia { @@ -37,10 +40,12 @@ namespace QuickMedia::FontLoader { return 0; } - sf::Font* get_font(FontType font_type) { - sf::Font *font = font_cache[(size_t)font_type].get(); - if(!font) { - auto new_font = std::make_unique(); + mgl::Font* get_font(FontType font_type, unsigned int character_size) { + // Make mgl font size match sfml font size + character_size += 5; + + mgl::MemoryMappedFile *mapped_file = font_file_cache[(unsigned int)font_type].get(); + if(!mapped_file) { std::vector noto_directories; std::string font_file_name; switch(font_type) { @@ -95,41 +100,54 @@ namespace QuickMedia::FontLoader { } } - bool successfully_loaded_font = false; + bool successfully_loaded_file = false; + auto new_memory_mapped_file = std::make_unique(); for(const std::string ¬o_dir : noto_directories) { - if(new_font->loadFromFile(noto_dir + "/" + font_file_name)) { - successfully_loaded_font = true; + if(new_memory_mapped_file->load((noto_dir + "/" + font_file_name).c_str(), mgl::MemoryMappedFile::LoadOptions{true, false})) { + successfully_loaded_file = true; break; } } - if(!successfully_loaded_font) - fprintf(stderr, "Warning: Failed to load font: %s\n", font_file_name.c_str()); + if(!successfully_loaded_file) { + fprintf(stderr, "Warning: Failed to load font file: %s\n", font_file_name.c_str()); + abort(); + } + + mapped_file = new_memory_mapped_file.get(); + font_file_cache[(unsigned int)font_type] = std::move(new_memory_mapped_file); + } + + mgl::Font *font = font_cache[(unsigned int)font_type][character_size].get(); + if(!font) { + auto new_font = std::make_unique(); + if(!new_font->load_from_file(*mapped_file, character_size)) { + fprintf(stderr, "Warning: Failed to load font at character size %u\n", character_size); + abort(); + } font = new_font.get(); - font_cache[(size_t)font_type] = std::move(new_font); - malloc_trim(0); + font_cache[(unsigned int)font_type][character_size] = std::move(new_font); } return font; } } namespace QuickMedia::TextureLoader { - sf::Texture* get_texture(const char *filepath) { + mgl::Texture* get_texture(const char *filepath, bool pixel_coordinates) { assert(!resource_root.empty()); std::string str = filepath; auto it = texture_cache.find(str); if(it != texture_cache.end()) return it->second.get(); - auto new_texture = std::make_unique(); - sf::Texture *result = new_texture.get(); - if(!new_texture->loadFromFile(resource_root + str)) + auto new_texture = std::make_unique(); + mgl::Texture *result = new_texture.get(); + if(!new_texture->load_from_file((resource_root + str).c_str(), mgl::Texture::LoadOptions{ false, pixel_coordinates })) fprintf(stderr, "Failed to load image: %s%s\n", resource_root.c_str(), filepath); - new_texture->setSmooth(true); texture_cache[str] = std::move(new_texture); malloc_trim(0); return result; } -} \ No newline at end of file +} diff --git a/src/RoundedRectangle.cpp b/src/RoundedRectangle.cpp index fc56823..587560c 100644 --- a/src/RoundedRectangle.cpp +++ b/src/RoundedRectangle.cpp @@ -1,68 +1,71 @@ #include "../include/RoundedRectangle.hpp" -#include -#include -#include +#include +#include #include namespace QuickMedia { static const float shadow_radius = 20.0f; // Has to match the shadow offset in rounded_rectangle.glsl - static std::atomic cached_radius = 0.0f; - static std::atomic cached_resolution_x = 0.0f; - static std::atomic cached_resolution_y = 0.0f; + static float cached_radius = 0.0f; + static float cached_resolution_x = 0.0f; + static float cached_resolution_y = 0.0f; - RoundedRectangle::RoundedRectangle(sf::Vector2f size, float radius, sf::Color color, sf::Shader *rounded_rectangle_shader) : + static float abs(float value) { + return value >= 0.0f ? value : -value; + } + + RoundedRectangle::RoundedRectangle(mgl::vec2f size, float radius, mgl::Color color, mgl::Shader *rounded_rectangle_shader) : radius(radius), pos(0.0f, 0.0f), size(size), rounded_rectangle_shader(rounded_rectangle_shader) { assert(rounded_rectangle_shader); set_color(color); - vertices[0].texCoords = sf::Vector2f(0.0f, 0.0f); - vertices[1].texCoords = sf::Vector2f(1.0f, 0.0f); - vertices[2].texCoords = sf::Vector2f(1.0f, 1.0f); - vertices[3].texCoords = sf::Vector2f(0.0f, 1.0f); + vertices[0].texcoords = mgl::vec2f(0.0f, 0.0f); + vertices[1].texcoords = mgl::vec2f(1.0f, 0.0f); + vertices[2].texcoords = mgl::vec2f(1.0f, 1.0f); + vertices[3].texcoords = mgl::vec2f(0.0f, 1.0f); } - void RoundedRectangle::set_position(sf::Vector2f pos) { + void RoundedRectangle::set_position(mgl::vec2f pos) { this->pos = pos; - const float shadow_radius_ins = rounded_rectangle_shader->getNativeHandle() == 0 ? 0.0f : shadow_radius; - vertices[0].position = pos + sf::Vector2f(-shadow_radius_ins, -shadow_radius_ins); - vertices[1].position = pos + sf::Vector2f(shadow_radius_ins, -shadow_radius_ins) + sf::Vector2f(size.x, 0.0f); - vertices[2].position = pos + sf::Vector2f(shadow_radius_ins, shadow_radius_ins) + sf::Vector2f(size.x, size.y); - vertices[3].position = pos + sf::Vector2f(-shadow_radius_ins, shadow_radius_ins) + sf::Vector2f(0.0f, size.y); + const float shadow_radius_ins = rounded_rectangle_shader->is_valid() ? shadow_radius : 0.0f; + vertices[0].position = pos + mgl::vec2f(-shadow_radius_ins, -shadow_radius_ins); + vertices[1].position = pos + mgl::vec2f(shadow_radius_ins, -shadow_radius_ins) + mgl::vec2f(size.x, 0.0f); + vertices[2].position = pos + mgl::vec2f(shadow_radius_ins, shadow_radius_ins) + mgl::vec2f(size.x, size.y); + vertices[3].position = pos + mgl::vec2f(-shadow_radius_ins, shadow_radius_ins) + mgl::vec2f(0.0f, size.y); } - void RoundedRectangle::set_size(sf::Vector2f size) { + void RoundedRectangle::set_size(mgl::vec2f size) { this->size = size; set_position(pos); } - void RoundedRectangle::set_color(sf::Color color) { + void RoundedRectangle::set_color(mgl::Color color) { for(size_t i = 0; i < 4; ++i) vertices[i].color = color; } - sf::Vector2f RoundedRectangle::get_position() const { + mgl::vec2f RoundedRectangle::get_position() const { return pos; } - sf::Vector2f RoundedRectangle::get_size() const { + mgl::vec2f RoundedRectangle::get_size() const { return size; } - void RoundedRectangle::draw(sf::RenderTarget &target) { - const sf::Vector2f resolution = size + sf::Vector2f(shadow_radius*2.0f, shadow_radius*2.0f); + void RoundedRectangle::draw(mgl::Window &target) { + const mgl::vec2f resolution = size + mgl::vec2f(shadow_radius*2.0f, shadow_radius*2.0f); - // TODO: Remove these for optimizations. Also do the same in other places where setUniform is called - if(std::abs(cached_radius - radius) > 0.01f) { - rounded_rectangle_shader->setUniform("radius", radius); + if(abs(cached_radius - radius) > 0.01f) { + // TODO: Remove these for optimizations. Also do the same in other places where set_uniform is called + rounded_rectangle_shader->set_uniform("radius", radius); cached_radius = radius; } - if(std::abs(cached_resolution_x - resolution.x) > 0.01f || std::abs(cached_resolution_y - resolution.y) > 0.01f) { - rounded_rectangle_shader->setUniform("resolution", size + sf::Vector2f(shadow_radius*2.0f, shadow_radius*2.0f)); + if(abs(cached_resolution_x - resolution.x) > 0.01f || abs(cached_resolution_y - resolution.y) > 0.01f) { + rounded_rectangle_shader->set_uniform("resolution", size + mgl::vec2f(shadow_radius*2.0f, shadow_radius*2.0f)); cached_resolution_x = resolution.x; cached_resolution_y = resolution.y; } - target.draw(vertices, 4, sf::Quads, rounded_rectangle_shader); + target.draw(vertices, 4, mgl::PrimitiveType::Quads, rounded_rectangle_shader); } } \ No newline at end of file diff --git a/src/SearchBar.cpp b/src/SearchBar.cpp index 33cea08..e6c51e9 100644 --- a/src/SearchBar.cpp +++ b/src/SearchBar.cpp @@ -4,28 +4,30 @@ #include "../include/ResourceLoader.hpp" #include "../include/Config.hpp" #include "../include/Utils.hpp" -#include -#include -#include +#include +#include +#include +#include #include #include -// TODO: Use a seperate placeholder sf::Text instead of switching the text to placeholder text.... +// TODO: Use a seperate placeholder mgl::Text instead of switching the text to placeholder text.... namespace QuickMedia { static const float background_margin_horizontal = 10.0f + std::floor(5.0f * get_config().scale); static const float padding_top_default = std::floor(10.0f * get_config().scale); static const float padding_bottom_default = std::floor(15.0f * get_config().scale); static const float background_margin_vertical = std::floor(4.0f * get_config().scale); + static const int character_size = get_config().search.font_size * get_config().scale * get_config().font_scale; - SearchBar::SearchBar(sf::Texture *plugin_logo, sf::Shader *rounded_rectangle_shader, const std::string &placeholder, bool input_masked) : + SearchBar::SearchBar(mgl::Texture *plugin_logo, mgl::Shader *rounded_rectangle_shader, const std::string &placeholder, bool input_masked) : onTextUpdateCallback(nullptr), onTextSubmitCallback(nullptr), onTextBeginTypingCallback(nullptr), - text_autosearch_delay(50), + text_autosearch_delay_ms(50), caret_visible(true), - text(placeholder, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(get_config().search.font_size * get_config().scale * get_config().font_scale)), - background(sf::Vector2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().selected_color, rounded_rectangle_shader), + text(placeholder, *FontLoader::get_font(FontLoader::FontType::LATIN, character_size)), + background(mgl::vec2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().selected_color, rounded_rectangle_shader), placeholder_str(placeholder), show_placeholder(true), updated_search(false), @@ -40,13 +42,13 @@ namespace QuickMedia { { padding_top = padding_top_default; padding_bottom = padding_bottom_default; - text.setFillColor(get_theme().placeholder_text_color); - shade.setFillColor(get_theme().shade_color); - if(plugin_logo && plugin_logo->getNativeHandle() != 0) - plugin_logo_sprite.setTexture(*plugin_logo, true); + text.set_color(get_theme().placeholder_text_color); + shade.set_color(get_theme().shade_color); + if(plugin_logo && plugin_logo->is_valid()) + plugin_logo_sprite.set_texture(plugin_logo); } - void SearchBar::draw(sf::RenderWindow &window, sf::Vector2f size, bool draw_background) { + void SearchBar::draw(mgl::Window &window, mgl::vec2f size, bool draw_background) { if(std::abs(size.x - prev_size.x) > 1.0f || std::abs(size.y - prev_size.y) > 1.0f) { needs_update = true; prev_size = size; @@ -63,17 +65,17 @@ namespace QuickMedia { background.draw(window); if(input_masked && !show_placeholder) { - std::string masked_str(text.getString().getSize(), '*'); - sf::Text masked_text(std::move(masked_str), *text.getFont(), text.getCharacterSize()); - masked_text.setPosition(text.getPosition()); + std::string masked_str(text.get_string().size(), '*'); + mgl::Text masked_text(std::move(masked_str), *text.get_font()); + masked_text.set_position(text.get_position()); window.draw(masked_text); - caret.setPosition(masked_text.findCharacterPos(masked_text.getString().getSize()) + sf::Vector2f(0.0f, 2.0f)); + caret.set_position(masked_text.find_character_pos(masked_text.get_string().size()) + mgl::vec2f(0.0f, character_size * 0.4f)); } else { window.draw(text); - if(show_placeholder || text.getString().isEmpty()) - caret.setPosition(text.getPosition() - sf::Vector2f(2.0f, 0.0f) + sf::Vector2f(0.0f, 2.0f)); + if(show_placeholder || text.get_string().empty()) + caret.set_position(text.get_position() - mgl::vec2f(2.0f, 0.0f) + mgl::vec2f(0.0f, character_size * 0.4f)); else - caret.setPosition(text.findCharacterPos(text.getString().getSize()) + sf::Vector2f(0.0f, 2.0f)); + caret.set_position(text.find_character_pos(text.get_string().size()) + mgl::vec2f(0.0f, character_size * 0.4f)); } if(caret_visible && is_editable()) @@ -83,16 +85,16 @@ namespace QuickMedia { window.draw(plugin_logo_sprite); } - void SearchBar::on_event(sf::Event &event) { - if(is_touch_enabled() && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) { - sf::FloatRect box(background.get_position(), background.get_size()); - if(box.contains(event.mouseButton.x, event.mouseButton.y)) + void SearchBar::on_event(mgl::Window &window, mgl::Event &event) { + if(is_touch_enabled() && event.type == mgl::Event::MouseButtonPressed && event.mouse_button.button == mgl::Mouse::Left) { + mgl::FloatRect box(background.get_position(), background.get_size()); + if(box.contains(mgl::vec2f(event.mouse_button.x, event.mouse_button.y))) mouse_left_inside = true; else mouse_left_inside = false; - } else if(is_touch_enabled() && event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left) { - sf::FloatRect box(background.get_position(), background.get_size()); - if(mouse_left_inside && box.contains(event.mouseButton.x, event.mouseButton.y)) + } else if(is_touch_enabled() && event.type == mgl::Event::MouseButtonReleased && event.mouse_button.button == mgl::Mouse::Left) { + mgl::FloatRect box(background.get_position(), background.get_size()); + if(mouse_left_inside && box.contains(mgl::vec2f(event.mouse_button.x, event.mouse_button.y))) show_virtual_keyboard(); mouse_left_inside = false; } @@ -100,63 +102,70 @@ namespace QuickMedia { if(!editable) return; - if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Backspace) + if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Backspace) backspace_pressed = true; - else if(event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Backspace) + else if(event.type == mgl::Event::KeyReleased && event.key.code == mgl::Keyboard::Backspace) backspace_pressed = false; - if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::V && event.key.control) { - auto clipboard = sf::Clipboard::getString().toUtf8(); - append_text(*(std::string*)&clipboard); + if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::V && event.key.control) { + append_text(window.get_clipboard()); } - if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::D && event.key.control) { - clear(); - updated_search = true; - time_since_search_update.restart(); - } - - if((sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl)) && (event.type != sf::Event::TextEntered || event.text.unicode != 13)) // Enter + if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::D && event.key.control) { + if(!text.get_string().empty()) { + clear(); + updated_search = true; + time_since_search_update.restart(); + } return; + } - if(event.type == sf::Event::TextEntered && event.text.unicode != 8 && event.text.unicode != 127) // 8 = backspace, 127 = del - onTextEntered(event.text.unicode); - else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Backspace) - onTextEntered(8); + if((window.is_key_pressed(mgl::Keyboard::LControl) || window.is_key_pressed(mgl::Keyboard::RControl)) && (event.type != mgl::Event::TextEntered || event.text.codepoint != 13)) // Enter + return; + + if(event.type == mgl::Event::TextEntered && event.text.codepoint != 8 && event.text.codepoint != 127) { // 8 = backspace, 127 = del + onTextEntered(event.text); + } else if(event.type == mgl::Event::KeyPressed && event.key.code == mgl::Keyboard::Backspace) { + mgl::Event::TextEvent text_event; + text_event.codepoint = 8; + text_event.size = 1; + text_event.str[0] = 8; + text_event.str[1] = '\0'; + onTextEntered(text_event); + } } void SearchBar::update() { - sf::Int32 elapsed_time = time_since_search_update.getElapsedTime().asMilliseconds(); - int timeout = text_autosearch_delay; + double elapsed_time_sec = time_since_search_update.get_elapsed_time_seconds(); + double timeout_sec = (double)text_autosearch_delay_ms * 0.001; if(backspace_pressed) - timeout = 750; - if(updated_search && elapsed_time >= timeout) { + timeout_sec = 0.75; + if(updated_search && elapsed_time_sec >= timeout_sec) { updated_search = false; - auto u8 = text.getString().toUtf8(); - std::string *u8_str = (std::string*)&u8; + std::string str = text.get_string(); if(show_placeholder) - u8_str->clear(); + str.clear(); if(onTextUpdateCallback) - onTextUpdateCallback(*u8_str); + onTextUpdateCallback(str); typing = false; } } - void SearchBar::onWindowResize(const sf::Vector2f &size) { - draw_logo = plugin_logo_sprite.getTexture() != nullptr; + void SearchBar::onWindowResize(const mgl::vec2f &size) { + draw_logo = plugin_logo_sprite.get_texture() != nullptr; if(size.x < 400.0f) draw_logo = false; - float font_height = text.getCharacterSize() + 7.0f; + float font_height = character_size + 7.0f; float rect_height = std::floor(font_height + background_margin_vertical * 2.0f); float offset_x; if(draw_logo) { - float one_line_height = std::floor(text.getCharacterSize() + 8.0f + background_margin_vertical * 2.0f); - auto texture_size = plugin_logo_sprite.getTexture()->getSize(); - sf::Vector2f texture_size_f(texture_size.x, texture_size.y); - sf::Vector2f new_size = wrap_to_size(texture_size_f, sf::Vector2f(200.0f, one_line_height)); - plugin_logo_sprite.setScale(get_ratio(texture_size_f, new_size)); - plugin_logo_sprite.setPosition(pos.x + padding_x, pos.y + padding_top + rect_height * 0.5f - plugin_logo_sprite.getTexture()->getSize().y * plugin_logo_sprite.getScale().y * 0.5f); + float one_line_height = std::floor(character_size + 8.0f + background_margin_vertical * 2.0f); + auto texture_size = plugin_logo_sprite.get_texture()->get_size(); + mgl::vec2f texture_size_f(texture_size.x, texture_size.y); + mgl::vec2f new_size = wrap_to_size(texture_size_f, mgl::vec2f(200.0f, one_line_height)); + plugin_logo_sprite.set_scale(get_ratio(texture_size_f, new_size)); + plugin_logo_sprite.set_position(mgl::vec2f(pos.x + padding_x, pos.y + padding_top + rect_height * 0.5f - plugin_logo_sprite.get_texture()->get_size().y * plugin_logo_sprite.get_scale().y * 0.5f)); offset_x = padding_x + new_size.x + 10.0f; } else { offset_x = padding_x; @@ -164,29 +173,32 @@ namespace QuickMedia { const float width = std::floor(size.x - offset_x - padding_x); - background.set_size(sf::Vector2f(width, rect_height)); - shade.setSize(sf::Vector2f(size.x, padding_top + rect_height + padding_bottom)); - caret.setSize(vec2f_floor(2.0f * get_config().scale, text.getCharacterSize() + std::floor(2.0f * get_config().scale))); + background.set_size(mgl::vec2f(width, rect_height)); + shade.set_size(mgl::vec2f(size.x, padding_top + rect_height + padding_bottom)); + caret.set_size(vec2f_floor(2.0f * get_config().scale, character_size + std::floor(2.0f * get_config().scale))); - background.set_position(sf::Vector2f(pos.x + offset_x, pos.y + padding_top)); - shade.setPosition(pos); - sf::Vector2f font_position(std::floor(pos.x + offset_x + background_margin_horizontal), std::floor(pos.y + padding_top + background_margin_vertical)); - text.setPosition(font_position); + background.set_position(mgl::vec2f(pos.x + offset_x, pos.y + padding_top)); + shade.set_position(pos); + mgl::vec2f font_position(std::floor(pos.x + offset_x + background_margin_horizontal), std::floor(pos.y + padding_top + background_margin_vertical - character_size * 0.3f)); + text.set_position(font_position); } - void SearchBar::onTextEntered(sf::Uint32 codepoint) { - if(codepoint == 8 && !show_placeholder) { // Backspace - sf::String str = text.getString(); - if(str.getSize() > 0) { + void SearchBar::onTextEntered(const mgl::Event::TextEvent &text_event) { + if(text_event.codepoint == 8 && !show_placeholder) { // Backspace + std::string str = text.get_string(); + if(str.size() > 0) { // TODO: When it's possible to move the cursor, then check at cursor position instead of end of the string - if(str[str.getSize() - 1] == '\n') + if(str[str.size() - 1] == '\n') needs_update = true; - str.erase(str.getSize() - 1, 1); - text.setString(str); - if(str.getSize() == 0) { + + const size_t codepoint_start_index = mgl::utf8_get_start_of_codepoint((const unsigned char*)str.c_str(), str.size(), str.size() - 1); + str.erase(codepoint_start_index); + const bool empty = str.empty(); + text.set_string(std::move(str)); + if(empty) { show_placeholder = true; - text.setString(placeholder_str); - text.setFillColor(get_theme().placeholder_text_color); + text.set_string(placeholder_str); + text.set_color(get_theme().placeholder_text_color); } if(!updated_search) { typing = true; @@ -196,18 +208,17 @@ namespace QuickMedia { updated_search = true; time_since_search_update.restart(); } - } else if(codepoint == 13) { // Return + } else if(text_event.codepoint == 13) { // Return backspace_pressed = false; if(onTextSubmitCallback) { - auto u8 = text.getString().toUtf8(); - std::string *u8_str = (std::string*)&u8; + std::string str = text.get_string(); if(show_placeholder) - u8_str->clear(); - onTextSubmitCallback(*u8_str); + str.clear(); + onTextSubmitCallback(str); } - } else if(codepoint > 31) { // Non-control character - append_text(sf::String(codepoint)); - } else if(codepoint == '\n') + } else if(text_event.codepoint > 31) { // Non-control character + append_text(std::string(text_event.str, text_event.size)); + } else if(text_event.codepoint == '\n') needs_update = true; } @@ -215,8 +226,8 @@ namespace QuickMedia { if(show_placeholder) return; show_placeholder = true; - text.setString(placeholder_str); - text.setFillColor(get_theme().placeholder_text_color); + text.set_string(placeholder_str); + text.set_color(get_theme().placeholder_text_color); needs_update = true; updated_search = false; backspace_pressed = false; @@ -238,13 +249,11 @@ namespace QuickMedia { if(show_placeholder) { show_placeholder = false; - text.setString(""); - text.setFillColor(sf::Color::White); + text.set_string(""); + text.set_color(mgl::Color(255, 255, 255, 255)); } - sf::String str = text.getString(); - str += sf::String::fromUtf8(text_to_add.begin(), text_to_add.end());; - text.setString(str); + text.append_string(text_to_add); if(!updated_search) { typing = true; @@ -258,7 +267,7 @@ namespace QuickMedia { needs_update = true; } - void SearchBar::set_position(sf::Vector2f pos) { + void SearchBar::set_position(mgl::vec2f pos) { if(std::abs(this->pos.x - pos.x) > 1.0f || std::abs(this->pos.y - pos.y) > 1.0f) { this->pos = pos; needs_update = true; @@ -274,18 +283,18 @@ namespace QuickMedia { } float SearchBar::getBottom() const { - return getBottomWithoutShadow() + 5.0f;//background_shadow.getSize().y; + return getBottomWithoutShadow() + 5.0f;//background_shadow.get_size().y; } float SearchBar::getBottomWithoutShadow() const { - float font_height = text.getCharacterSize() + 7.0f; + float font_height = character_size + 7.0f; return std::floor(font_height + background_margin_vertical * 2.0f + padding_top + padding_bottom); } std::string SearchBar::get_text() const { if(show_placeholder) return ""; - return text.getString(); + return text.get_string(); } bool SearchBar::is_empty() const { diff --git a/src/SfmlFixes.cpp b/src/SfmlFixes.cpp deleted file mode 100644 index d6d4b17..0000000 --- a/src/SfmlFixes.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "../include/SfmlFixes.hpp" -#include - -static std::mutex mutex; -namespace QuickMedia { - bool load_image_from_file(sf::Image &image, const std::string &filepath) { - std::lock_guard lock(mutex); - return image.loadFromFile(filepath); - } - - bool load_image_from_memory(sf::Image &image, const void *data, size_t size) { - std::lock_guard lock(mutex); - return image.loadFromMemory(data, size); - } -} \ No newline at end of file diff --git a/src/Tabs.cpp b/src/Tabs.cpp index 4605f2c..db25ffb 100644 --- a/src/Tabs.cpp +++ b/src/Tabs.cpp @@ -4,8 +4,10 @@ #include "../include/Utils.hpp" #include "../include/Config.hpp" #include "../include/Theme.hpp" -#include -#include +#include "../include/Scale.hpp" +#include +#include +#include #include namespace QuickMedia { @@ -24,15 +26,16 @@ namespace QuickMedia { return tab_height + std::floor(10.0f * get_config().scale); } - Tabs::Tabs(sf::Shader *rounded_rectangle_shader, sf::Color shade_color) : background(sf::Vector2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().selected_color, rounded_rectangle_shader), shade_color(shade_color) { - shade.setFillColor(shade_color); + Tabs::Tabs(mgl::Shader *rounded_rectangle_shader, mgl::Color shade_color) : background(mgl::vec2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().selected_color, rounded_rectangle_shader), shade_color(shade_color) { + shade.set_color(shade_color); + arrow_sprite.set_texture(TextureLoader::get_texture("images/arrow.png")); } - Tabs::Tabs(sf::Shader *rounded_rectangle_shader) : Tabs(rounded_rectangle_shader, get_theme().shade_color) {} + Tabs::Tabs(mgl::Shader *rounded_rectangle_shader) : Tabs(rounded_rectangle_shader, get_theme().shade_color) {} - int Tabs::add_tab(const std::string &title, Body *body) { + int Tabs::add_tab(std::string title, Body *body) { assert(body); - tabs.push_back({ sf::Text(title, *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size), title, body} ); + tabs.push_back({ mgl::Text(std::move(title), *FontLoader::get_font(FontLoader::FontType::LATIN, tab_text_size)), body} ); return tabs.size() - 1; } @@ -62,13 +65,13 @@ namespace QuickMedia { on_change_tab(prev_tab, selected_tab); } - void Tabs::on_event(sf::Event &event) { - if(event.type == sf::Event::KeyPressed && event.key.control && !tabs.empty()) { - bool move_left = (event.key.code == sf::Keyboard::Left || (event.key.alt && event.key.code == sf::Keyboard::H)); - move_left |= (event.key.code == sf::Keyboard::Tab && event.key.shift); + void Tabs::on_event(mgl::Event &event) { + if(event.type == mgl::Event::KeyPressed && event.key.control && !tabs.empty()) { + bool move_left = (event.key.code == mgl::Keyboard::Left || (event.key.alt && event.key.code == mgl::Keyboard::H)); + move_left |= (event.key.code == mgl::Keyboard::Tab && event.key.shift); - bool move_right = (event.key.code == sf::Keyboard::Right || (event.key.alt && event.key.code == sf::Keyboard::L)); - move_right |= (event.key.code == sf::Keyboard::Tab && !event.key.shift); + bool move_right = (event.key.code == mgl::Keyboard::Right || (event.key.alt && event.key.code == mgl::Keyboard::L)); + move_right |= (event.key.code == mgl::Keyboard::Tab && !event.key.shift); if(move_left) { if(selected_tab > 0) @@ -76,37 +79,33 @@ namespace QuickMedia { } else if(move_right) { if(selected_tab < (int)tabs.size() - 1) move_selected_tab(selected_tab + 1); - } else if(event.key.code >= sf::Keyboard::Num1 && event.key.code <= sf::Keyboard::Num9) { - const int tab_target = event.key.code - sf::Keyboard::Num1; + } else if(event.key.code >= mgl::Keyboard::Num1 && event.key.code <= mgl::Keyboard::Num9) { + const int tab_target = event.key.code - mgl::Keyboard::Num1; if(tab_target < (int)tabs.size()) move_selected_tab(tab_target); } } } - static sf::View create_scissor_view(sf::Vector2f pos, sf::Vector2f size, const sf::Vector2f window_size) { - sf::View view(sf::FloatRect(0.0f, 0.0f, size.x, size.y)); - view.setViewport(sf::FloatRect( - pos.x / (float)window_size.x, pos.y / (float)window_size.y, - size.x / (float)window_size.x, size.y / (float)window_size.y)); + static mgl::View create_scissor_view(mgl::vec2f pos, mgl::vec2f size) { + mgl::View view = { mgl::vec2i(pos.x, pos.y), mgl::vec2i(size.x, size.y) }; return view; } - void Tabs::draw(sf::RenderWindow &window, sf::Vector2f pos, float width) { + void Tabs::draw(mgl::Window &window, mgl::vec2f pos, float width) { if(width - tab_margin_x < 0.0f || tabs.empty()) return; - auto window_size = window.getSize(); container_width = width; const int num_visible_tabs = std::min((int)tabs.size(), std::max(1, (int)(width / tab_min_width))); width_per_tab = std::floor(width / num_visible_tabs); - const float tab_text_y = std::floor(pos.y + tab_height*0.5f - (tab_text_size + 5.0f*get_config().scale)*0.5f); + const float tab_text_y = std::floor(pos.y + tab_height*0.5f - (tab_text_size + 13.0f*get_config().scale)*0.5f); tab_background_width = std::floor(width_per_tab - tab_margin_x*2.0f); - background.set_size(sf::Vector2f(tab_background_width, tab_height)); + background.set_size(mgl::vec2f(tab_background_width, tab_height)); - if(shade_color != sf::Color::Transparent) { - shade.setSize(sf::Vector2f(width, get_shade_height())); - shade.setPosition(std::floor(pos.x), std::floor(pos.y)); + if(shade_color != mgl::Color(0, 0, 0, 0)) { + shade.set_size(mgl::vec2f(width, get_shade_height())); + shade.set_position(mgl::vec2f(std::floor(pos.x), std::floor(pos.y))); window.draw(shade); } @@ -127,7 +126,7 @@ namespace QuickMedia { bool tabs_cutoff_right = false; const auto start_pos = pos; - const sf::View prev_view = window.getView(); + const mgl::View prev_view = window.get_view(); pos.x += scroll_fixed; for(size_t i = 0; i < tabs.size(); ++i) { @@ -142,83 +141,77 @@ namespace QuickMedia { } if((int)index == selected_tab) { - background.set_position(sf::Vector2f(background_pos_x, std::floor(pos.y))); + background.set_position(mgl::vec2f(background_pos_x, std::floor(pos.y))); background.draw(window); } - sf::Text &tab_text = tabs[index].text; - float text_pos_x = std::floor(pos.x + i*width_per_tab + width_per_tab*0.5f - tab_text.getLocalBounds().width*0.5f); + mgl::Text &tab_text = tabs[index].text; + float text_pos_x = std::floor(pos.x + i*width_per_tab + width_per_tab*0.5f - tab_text.get_bounds().size.x*0.5f); text_pos_x = std::max(text_pos_x, background_pos_x); - window.setView(create_scissor_view({ text_pos_x, tab_text_y }, { tab_background_width, tab_height }, { (float)window_size.x, (float)window_size.y })); + window.set_view(create_scissor_view({ text_pos_x, tab_text_y }, { tab_background_width, tab_height })); window.draw(tab_text); - window.setView(prev_view); + window.set_view(prev_view); } - float lw = std::floor(25.0f * get_config().scale); - float lh = background.get_size().y; - - float line_offset_y = std::floor(lw * 0.35f); + const float lw = std::floor(25.0f * get_config().scale); + const float lh = background.get_size().y; if(tabs_cutoff_left) { - sf::Vertex gradient_points[4]; - gradient_points[0].position = sf::Vector2f(start_pos.x + tab_margin_x, start_pos.y); - gradient_points[1].position = sf::Vector2f(start_pos.x + tab_margin_x + lw, start_pos.y); - gradient_points[2].position = sf::Vector2f(start_pos.x + tab_margin_x + lw, start_pos.y + lh); - gradient_points[3].position = sf::Vector2f(start_pos.x + tab_margin_x, start_pos.y + lh); + mgl::Vertex gradient_points[4]; + gradient_points[0].position = mgl::vec2f(start_pos.x + tab_margin_x, start_pos.y); + gradient_points[1].position = mgl::vec2f(start_pos.x + tab_margin_x + lw, start_pos.y); + gradient_points[2].position = mgl::vec2f(start_pos.x + tab_margin_x + lw, start_pos.y + lh); + gradient_points[3].position = mgl::vec2f(start_pos.x + tab_margin_x, start_pos.y + lh); gradient_points[0].color = shade_color; - gradient_points[1].color = sf::Color(shade_color.r, shade_color.g, shade_color.b, 10); - gradient_points[2].color = sf::Color(shade_color.r, shade_color.g, shade_color.b, 10); + gradient_points[1].color = mgl::Color(shade_color.r, shade_color.g, shade_color.b, 10); + gradient_points[2].color = mgl::Color(shade_color.r, shade_color.g, shade_color.b, 10); gradient_points[3].color = shade_color; - window.draw(gradient_points, 4, sf::Quads); - - sf::RectangleShape line(vec2f_floor(10.0f * get_config().scale, 2.0f * get_config().scale)); - line.setFillColor(get_theme().arrow_color); - line.setOrigin(line.getSize().x * 0.5f, line.getSize().y * 0.5f); - - line.rotate(-45.0f); - line.setPosition(std::floor(start_pos.x + line.getLocalBounds().width), std::floor(pos.y + background.get_size().y * 0.5f - lh * 0.5f + line_offset_y)); - window.draw(line); - - line.rotate(-90.0f); - line.setPosition(std::floor(start_pos.x + line.getLocalBounds().width), std::floor(pos.y + background.get_size().y * 0.5f - lh * 0.5f + line_offset_y + std::floor(7.0f * get_config().scale))); - window.draw(line); + window.draw(gradient_points, 4, mgl::PrimitiveType::Quads); + + mgl::vec2i arrow_sprite_width = arrow_sprite.get_texture()->get_size(); + arrow_sprite_width.y = arrow_sprite_width.x; + const mgl::vec2f arrow_scale_ratio = get_ratio(arrow_sprite_width, clamp_to_size_y(arrow_sprite_width, (int)lh - 8)); + arrow_sprite.set_scale(arrow_scale_ratio); + arrow_sprite.set_origin(arrow_sprite.get_texture()->get_size().to_vec2f() * 0.5f); + arrow_sprite.set_position(start_pos + mgl::vec2f((int)(arrow_sprite.get_texture()->get_size().x * 0.5f * arrow_scale_ratio.x) + 5, (int)(lh * 0.5f))); + arrow_sprite.set_rotation(-90.0f); + arrow_sprite.set_color(get_theme().arrow_color); + window.draw(arrow_sprite); } if(tabs_cutoff_right) { - sf::Vertex gradient_points[4]; - gradient_points[0].position = sf::Vector2f(start_pos.x + width - lw - tab_margin_x, start_pos.y); - gradient_points[1].position = sf::Vector2f(start_pos.x + width, start_pos.y); - gradient_points[2].position = sf::Vector2f(start_pos.x + width, start_pos.y + lh); - gradient_points[3].position = sf::Vector2f(start_pos.x + width - lw - tab_margin_x, start_pos.y + lh); + mgl::Vertex gradient_points[4]; + gradient_points[0].position = mgl::vec2f(start_pos.x + width - lw - tab_margin_x, start_pos.y); + gradient_points[1].position = mgl::vec2f(start_pos.x + width, start_pos.y); + gradient_points[2].position = mgl::vec2f(start_pos.x + width, start_pos.y + lh); + gradient_points[3].position = mgl::vec2f(start_pos.x + width - lw - tab_margin_x, start_pos.y + lh); - gradient_points[0].color = sf::Color(shade_color.r, shade_color.g, shade_color.b, 10); + gradient_points[0].color = mgl::Color(shade_color.r, shade_color.g, shade_color.b, 10); gradient_points[1].color = shade_color; gradient_points[2].color = shade_color; - gradient_points[3].color = sf::Color(shade_color.r, shade_color.g, shade_color.b, 10); - - window.draw(gradient_points, 4, sf::Quads); - - sf::RectangleShape line(vec2f_floor(10.0f * get_config().scale, 2.0f * get_config().scale)); - line.setFillColor(get_theme().arrow_color); - line.setOrigin(line.getSize().x * 0.5f, line.getSize().y * 0.5f); - - line.rotate(45.0f); - line.setPosition(std::floor(start_pos.x + width - lw*0.75f + line.getLocalBounds().width), std::floor(pos.y + background.get_size().y * 0.5f - lh * 0.5f + line_offset_y)); - window.draw(line); - - line.rotate(-90.0f); - line.setPosition(std::floor(start_pos.x + width - lw*0.75f + line.getLocalBounds().width), std::floor(pos.y + background.get_size().y * 0.5f - lh * 0.5f + line_offset_y + std::floor(7.0f * get_config().scale))); - window.draw(line); + gradient_points[3].color = mgl::Color(shade_color.r, shade_color.g, shade_color.b, 10); + + window.draw(gradient_points, 4, mgl::PrimitiveType::Quads); + + mgl::vec2i arrow_sprite_width = arrow_sprite.get_texture()->get_size(); + arrow_sprite_width.y = arrow_sprite_width.x; + const mgl::vec2f arrow_scale_ratio = get_ratio(arrow_sprite_width, clamp_to_size_y(arrow_sprite_width, (int)lh - 8)); + arrow_sprite.set_scale(arrow_scale_ratio); + arrow_sprite.set_origin(arrow_sprite.get_texture()->get_size().to_vec2f() * 0.5f); + arrow_sprite.set_position(start_pos + mgl::vec2f(width - (int)(arrow_sprite.get_texture()->get_size().x * 0.5f * arrow_scale_ratio.x) - 5, (int)(lh * 0.5f))); + arrow_sprite.set_rotation(90.0f); + arrow_sprite.set_color(get_theme().arrow_color); + window.draw(arrow_sprite); } } void Tabs::set_text(int index, const std::string &text) { - if(index < 0 || index >= (int)tabs.size() || text == tabs[index].label_utf8) return; - tabs[index].text.setString(sf::String::fromUtf8(text.begin(), text.end())); - tabs[index].label_utf8 = text; + if(index < 0 || index >= (int)tabs.size() || text == tabs[index].text.get_string()) + return; + tabs[index].text.set_string(text); } void Tabs::set_selected(int index) { diff --git a/src/Text.cpp b/src/Text.cpp index 14aebb1..69d6664 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -3,13 +3,13 @@ #include "../include/Config.hpp" #include "../include/Theme.hpp" #include "../generated/Emoji.hpp" -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include -#include namespace QuickMedia { @@ -21,19 +21,8 @@ namespace QuickMedia static const size_t FONT_INDEX_SYMBOLS = 2; static const size_t FONT_INDEX_EMOJI = 3; static const size_t FONT_ARRAY_SIZE = 4; - - size_t StringViewUtf32::find(const StringViewUtf32 &other, size_t offset) const { - if(offset >= size) - return -1; - - auto it = std::search(data + offset, data + size - offset, std::boyer_moore_searcher(other.data, other.data + other.size)); - if(it != data + size) - return it - data; - - return -1; - } - Text::Text(sf::String _str, bool bold_font, unsigned int characterSize, float maxWidth, bool highlight_urls) : + Text::Text(std::string _str, bool bold_font, unsigned int characterSize, float maxWidth, bool highlight_urls) : bold_font(bold_font), characterSize(characterSize), maxWidth(maxWidth), @@ -50,52 +39,54 @@ namespace QuickMedia caretIndex(0), caret_offset_x(0.0f) { - for(size_t i = 0; i < FONT_ARRAY_SIZE; ++i) { - vertices[i].setPrimitiveType(sf::PrimitiveType::Triangles); - vertex_buffers[i] = sf::VertexBuffer(sf::PrimitiveType::Triangles, sf::VertexBuffer::Static); - } setString(std::move(_str)); } - void Text::setString(const sf::String &str) + void Text::setString(std::string str) { //if(str != this->str) //{ - size_t prev_str_size = this->str.getSize(); - this->str = str; + size_t prev_str_size = this->str.size(); + this->str = std::move(str); dirty = true; dirtyText = true; - if((int)this->str.getSize() < caretIndex || prev_str_size == 0) + if((int)this->str.size() < caretIndex || prev_str_size == 0) { - caretIndex = this->str.getSize(); + caretIndex = this->str.size(); dirtyCaret = true; } // } } - const sf::String& Text::getString() const + const std::string& Text::getString() const { return str; } - void Text::appendText(const sf::String &str) { + void Text::appendText(const std::string &str) { this->str += str; dirty = true; dirtyText = true; } + + void Text::insert_text_at_caret_position(const std::string &str) { + this->str.insert(caretIndex, str); + dirty = true; + dirtyText = true; + } - void Text::setPosition(float x, float y) + void Text::set_position(float x, float y) { position.x = x; position.y = y; } - void Text::setPosition(const sf::Vector2f &position) + void Text::set_position(const mgl::vec2f &position) { this->position = position; } - sf::Vector2f Text::getPosition() const + mgl::vec2f Text::get_position() const { return position; } @@ -106,7 +97,7 @@ namespace QuickMedia if(std::abs(maxWidth - this->maxWidth) > 1.0f) { this->maxWidth = maxWidth; - if(num_lines > 1 || maxWidth < boundingBox.width) { + if(num_lines > 1 || maxWidth < boundingBox.size.x) { dirty = true; dirtyCaret = true; } @@ -127,13 +118,13 @@ namespace QuickMedia } } - unsigned int Text::getCharacterSize() const + unsigned int Text::get_character_size() const { return characterSize; } - void Text::replace(size_t start_index, size_t length, const sf::String &insert_str) { - int string_diff = (int)insert_str.getSize() - (int)length; + void Text::replace(size_t start_index, size_t length, const std::string &insert_str) { + int string_diff = (int)insert_str.size() - (int)length; str.replace(start_index, length, insert_str); dirty = true; dirtyText = true; @@ -147,7 +138,7 @@ namespace QuickMedia return caretIndex; } - void Text::setFillColor(sf::Color color) + void Text::set_color(mgl::Color color) { if(color != this->color) { @@ -197,16 +188,16 @@ namespace QuickMedia float Text::getWidth() const { - return boundingBox.width; + return boundingBox.size.x; } float Text::getHeight() const { - return boundingBox.height; + return boundingBox.size.y; } // TODO: Is there a more efficient way to do this? maybe japanese characters have a specific bit-pattern? - static bool is_japanese_codepoint(sf::Uint32 codepoint) { + static bool is_japanese_codepoint(uint32_t codepoint) { return (codepoint >= 0x2E80 && codepoint <= 0x2FD5) // Kanji radicals || (codepoint >= 0x3000 && codepoint <= 0x303F) // Punctuation || (codepoint >= 0x3041 && codepoint <= 0x3096) // Hiragana @@ -221,12 +212,12 @@ namespace QuickMedia || (codepoint >= 0xFF5F && codepoint <= 0xFF9F); // Katakana and punctuation (half width) } - static bool is_korean_codepoint(sf::Uint32 codepoint) { + static bool is_korean_codepoint(uint32_t codepoint) { return codepoint >= 0xAC00 && codepoint <= 0xD7A3; } // TODO: Is there a more efficient way to do this? maybe chinese characters have a specific bit-pattern? - static bool is_chinese_codepoint(sf::Uint32 codepoint) { + static bool is_chinese_codepoint(uint32_t codepoint) { return (codepoint >= 0x4E00 && codepoint <= 0x9FFF) // CJK Unified Ideographs || (codepoint >= 0x3400 && codepoint <= 0x4DBF) // CJK Unified Ideographs Extension A || (codepoint >= 0x20000 && codepoint <= 0x2A6DF) // CJK Unified Ideographs Extension B @@ -238,44 +229,84 @@ namespace QuickMedia } // TODO: Merge chinese, japanese and korean codepoints into one function since they share ranges - static bool is_cjk_codepoint(sf::Uint32 codepoint) { + static bool is_cjk_codepoint(uint32_t codepoint) { return is_chinese_codepoint(codepoint) || is_japanese_codepoint(codepoint) || is_korean_codepoint(codepoint); } - static bool is_symbol_codepoint(sf::Uint32 codepoint) { + static bool is_symbol_codepoint(uint32_t codepoint) { // TODO: Add the remaining NotoSansSymbols2-Regular.ttf codepoints as well. // See codepoint ranges with: fc-query --format='%{charset}\n' /usr/share/fonts/noto/NotoSansSymbols2-Regular.ttf. return codepoint >= 0x2800 && codepoint <= 0x28FF; // Braille } - static size_t find_end_of_cjk(const sf::Uint32 *str, size_t size) { - for(size_t i = 0; i < size; ++i) { - if(!is_cjk_codepoint(str[i])) + static size_t find_end_of_cjk(const char *str, size_t size) { + for(size_t i = 0; i < size;) { + const unsigned char *cp = (const unsigned char*)&str[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, size - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + + if(!is_cjk_codepoint(codepoint)) return i; + + i += clen; } return size; } - static size_t find_end_of_emoji(const sf::Uint32 *str, size_t size) { - for(size_t i = 0; i < size; ++i) { - if(!codepoint_is_emoji(str[i])) + static size_t find_end_of_emoji(const char *str, size_t size) { + for(size_t i = 0; i < size;) { + const unsigned char *cp = (const unsigned char*)&str[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, size - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + + if(!codepoint_is_emoji(codepoint)) return i; + + i += clen; } return size; } - static size_t find_end_of_symbol(const sf::Uint32 *str, size_t size) { - for(size_t i = 0; i < size; ++i) { - if(!is_symbol_codepoint(str[i])) + static size_t find_end_of_symbol(const char *str, size_t size) { + for(size_t i = 0; i < size;) { + const unsigned char *cp = (const unsigned char*)&str[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, size - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + + if(!is_symbol_codepoint(codepoint)) return i; + + i += clen; } return size; } - static size_t find_end_latin(const sf::Uint32 *str, size_t size) { - for(size_t i = 0; i < size; ++i) { - if(is_cjk_codepoint(str[i]) || codepoint_is_emoji(str[i]) || is_symbol_codepoint(str[i])) + static size_t find_end_latin(const char *str, size_t size) { + for(size_t i = 0; i < size;) { + const unsigned char *cp = (const unsigned char*)&str[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, size - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + + if(is_cjk_codepoint(codepoint) || codepoint_is_emoji(codepoint) || is_symbol_codepoint(codepoint)) return i; + + i += clen; } return size; } @@ -283,30 +314,39 @@ namespace QuickMedia void Text::splitTextByFont() { textElements.clear(); size_t index = 0; - size_t size = str.getSize(); + size_t size = str.size(); while(index < size) { + const unsigned char *cp = (const unsigned char*)&str[index]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, size - index, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + size_t offset; TextElement::TextType text_type = TextElement::TextType::LATIN; - if(is_symbol_codepoint(str[index])) { + if(is_symbol_codepoint(codepoint)) { text_type = TextElement::TextType::SYMBOL; - offset = find_end_of_symbol(str.getData() + index + 1, size - index - 1); - } else if(is_cjk_codepoint(str[index])) { + offset = find_end_of_symbol(str.data() + index, size - index); + } else if(is_cjk_codepoint(codepoint)) { text_type = TextElement::TextType::CJK; - offset = find_end_of_cjk(str.getData() + index + 1, size - index - 1); - } else if(codepoint_is_emoji(str[index])) { + offset = find_end_of_cjk(str.data() + index, size - index); + } else if(codepoint_is_emoji(codepoint)) { text_type = TextElement::TextType::EMOJI; - offset = find_end_of_emoji(str.getData() + index + 1, size - index - 1); + offset = find_end_of_emoji(str.data() + index, size - index); } else { - offset = find_end_latin(str.getData() + index + 1, size - index - 1); + offset = find_end_latin(str.data() + index, size - index); } - textElements.push_back({ StringViewUtf32(str.getData() + index, offset + 1), TextElement::Type::TEXT }); + + textElements.push_back({ std::string_view(str.data() + index, offset), TextElement::Type::TEXT }); textElements.back().text_type = text_type; - index += 1 + offset; + index += offset; } } - float Text::font_get_real_height(sf::Font *font) { - return font->getGlyph('|', characterSize, false).bounds.height + std::floor(4.0f * ((float)characterSize / (float)14.0f)); + float Text::font_get_real_height(mgl::Font *font) { + return font->get_glyph('|').size.y + std::floor(4.0f * ((float)characterSize / (float)14.0f)); } float Text::get_text_quad_left_side(const VertexRef &vertex_ref) const { @@ -350,7 +390,7 @@ namespace QuickMedia } } - sf::Uint32 Text::get_vertex_codepoint(int index) const { + uint32_t Text::get_vertex_codepoint(int index) const { const int num_vertices = vertices_linear.size(); if(num_vertices == 0) { return 0; @@ -368,10 +408,7 @@ namespace QuickMedia splitTextByFont(); // TODO: Optimize if(highlight_urls) { - auto u8 = str.toUtf8(); - std::string *u8_str = (std::string*)&u8; - url_ranges = extract_urls(*u8_str); - convert_utf8_to_utf32_ranges(*u8_str, url_ranges); + url_ranges = extract_urls(str); } else { url_ranges.clear(); } @@ -384,81 +421,88 @@ namespace QuickMedia vertices_linear.clear(); for(size_t i = 0; i < FONT_ARRAY_SIZE; ++i) { vertices[i].clear(); - vertices[i].resize(0); + vertices[i].shrink_to_fit(); } - boundingBox = sf::FloatRect(); + boundingBox = mgl::FloatRect(mgl::vec2f(0.0f, 0.0f), mgl::vec2f(0.0f, 0.0f)); - sf::Font *latin_font; + mgl::Font *latin_font; if(bold_font) - latin_font = FontLoader::get_font(FontLoader::FontType::LATIN_BOLD); + latin_font = FontLoader::get_font(FontLoader::FontType::LATIN_BOLD, characterSize); else - latin_font = FontLoader::get_font(FontLoader::FontType::LATIN); + latin_font = FontLoader::get_font(FontLoader::FontType::LATIN, characterSize); - const float latin_font_width = latin_font->getGlyph(' ', characterSize, false).advance; + const float latin_font_width = latin_font->get_glyph(' ').advance; const float hspace = latin_font_width + characterSpacing; const float vspace = font_get_real_height(latin_font); const float emoji_scale = vspace / 20.0f; - const sf::Color url_color = get_theme().url_text_color; + const mgl::Color url_color = get_theme().url_text_color; size_t url_range_index = 0; - sf::Vector2f glyphPos; - sf::Uint32 prevCodePoint = 0; + mgl::vec2f glyphPos; + uint32_t prevCodePoint = 0; // TODO: Only do this if dirtyText (then the Text object shouldn't be reset in Body. There should be a cleanup function in text instead) for(usize textElementIndex = 0; textElementIndex < textElements.size(); ++textElementIndex) { TextElement &textElement = textElements[textElementIndex]; - const sf::Font *ff = latin_font; + mgl::Font *ff = latin_font; int vertices_index = FONT_INDEX_LATIN; prevCodePoint = 0; if(textElement.text_type == TextElement::TextType::CJK) { - ff = FontLoader::get_font(FontLoader::FontType::CJK); + ff = FontLoader::get_font(FontLoader::FontType::CJK, characterSize); vertices_index = FONT_INDEX_CJK; } else if(textElement.text_type == TextElement::TextType::SYMBOL) { - ff = FontLoader::get_font(FontLoader::FontType::SYMBOLS); + ff = FontLoader::get_font(FontLoader::FontType::SYMBOLS, characterSize); vertices_index = FONT_INDEX_SYMBOLS; } else if(textElement.text_type == TextElement::TextType::EMOJI) { vertices_index = FONT_INDEX_EMOJI; - textElement.position = glyphPos; - sf::Color emoji_color(255, 255, 255, color.a); - for(size_t i = 0; i < textElement.text.size; ++i) + mgl::Color emoji_color(255, 255, 255, color.a); + for(size_t i = 0; i < textElement.text.size();) { - sf::Uint32 codePoint = textElement.text[i]; - int vertexStart = vertices[vertices_index].getVertexCount(); - EmojiRectangle emoji_rec = emoji_get_extents(codePoint); - + const unsigned char *cp = (const unsigned char*)&textElement.text[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, textElement.text.size() - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + + int vertexStart = vertices[vertices_index].size(); + EmojiRectangle emoji_rec = emoji_get_extents(codepoint); + const float font_height_offset = std::floor(-vspace * 0.2f); - sf::Vector2f vertexTopLeft(glyphPos.x, glyphPos.y + font_height_offset - std::floor(emoji_rec.height * emoji_scale) * 0.5f); - sf::Vector2f vertexTopRight(glyphPos.x + std::floor(emoji_rec.width * emoji_scale), glyphPos.y + font_height_offset - std::floor(emoji_rec.height * emoji_scale) * 0.5f); - sf::Vector2f vertexBottomLeft(glyphPos.x, glyphPos.y + font_height_offset + emoji_rec.height * emoji_scale * 0.5f); - sf::Vector2f vertexBottomRight(glyphPos.x + std::floor(emoji_rec.width * emoji_scale), glyphPos.y + font_height_offset + std::floor(emoji_rec.height * emoji_scale) * 0.5f); + mgl::vec2f vertexTopLeft(glyphPos.x, glyphPos.y + font_height_offset - std::floor(emoji_rec.height * emoji_scale) * 0.5f); + mgl::vec2f vertexTopRight(glyphPos.x + std::floor(emoji_rec.width * emoji_scale), glyphPos.y + font_height_offset - std::floor(emoji_rec.height * emoji_scale) * 0.5f); + mgl::vec2f vertexBottomLeft(glyphPos.x, glyphPos.y + font_height_offset + emoji_rec.height * emoji_scale * 0.5f); + mgl::vec2f vertexBottomRight(glyphPos.x + std::floor(emoji_rec.width * emoji_scale), glyphPos.y + font_height_offset + std::floor(emoji_rec.height * emoji_scale) * 0.5f); - sf::Vector2f textureTopLeft(emoji_rec.x, emoji_rec.y); - sf::Vector2f textureTopRight(emoji_rec.x + emoji_rec.width, emoji_rec.y); - sf::Vector2f textureBottomLeft(emoji_rec.x, emoji_rec.y + emoji_rec.height); - sf::Vector2f textureBottomRight(emoji_rec.x + emoji_rec.width, emoji_rec.y + emoji_rec.height); + mgl::vec2f textureTopLeft(emoji_rec.x, emoji_rec.y); + mgl::vec2f textureTopRight(emoji_rec.x + emoji_rec.width, emoji_rec.y); + mgl::vec2f textureBottomLeft(emoji_rec.x, emoji_rec.y + emoji_rec.height); + mgl::vec2f textureBottomRight(emoji_rec.x + emoji_rec.width, emoji_rec.y + emoji_rec.height); - vertices[vertices_index].append({ vertexTopRight, emoji_color, textureTopRight }); - vertices[vertices_index].append({ vertexTopLeft, emoji_color, textureTopLeft }); - vertices[vertices_index].append({ vertexBottomLeft, emoji_color, textureBottomLeft }); - vertices[vertices_index].append({ vertexBottomLeft, emoji_color, textureBottomLeft }); - vertices[vertices_index].append({ vertexBottomRight, emoji_color, textureBottomRight }); - vertices[vertices_index].append({ vertexTopRight, emoji_color, textureTopRight }); + vertices[vertices_index].emplace_back(vertexTopRight, textureTopRight, emoji_color); + vertices[vertices_index].emplace_back(vertexTopLeft, textureTopLeft, emoji_color); + vertices[vertices_index].emplace_back(vertexBottomLeft, textureBottomLeft, emoji_color); + vertices[vertices_index].emplace_back(vertexBottomLeft, textureBottomLeft, emoji_color); + vertices[vertices_index].emplace_back(vertexBottomRight, textureBottomRight, emoji_color); + vertices[vertices_index].emplace_back(vertexTopRight, textureTopRight, emoji_color); glyphPos.x += std::floor(emoji_rec.width * emoji_scale) + characterSpacing; - vertices_linear.push_back({vertices_index, vertexStart, 0, codePoint}); + vertices_linear.push_back({vertices_index, vertexStart, 0, codepoint}); + + i += clen; } continue; } - //vertices[vertices_index].resize(vertices[vertices_index].getVertexCount() + 4 * textElement.text.size); // TODO: Precalculate - textElement.position = glyphPos; - for(size_t i = 0; i < textElement.text.size; ++i) + //vertices[vertices_index].resize(vertices[vertices_index].size() + 4 * textElement.text.size); // TODO: Precalculate + for(size_t i = 0; i < textElement.text.size();) { - sf::Color text_color = color; + mgl::Color text_color = color; if(url_range_index < url_ranges.size()) { - size_t string_offset = (textElement.text.data + i) - str.getData(); + size_t string_offset = (textElement.text.data() + i) - str.data(); if(string_offset >= url_ranges[url_range_index].start && string_offset < url_ranges[url_range_index].start + url_ranges[url_range_index].length) { text_color = url_color; text_color.a = color.a; @@ -467,96 +511,107 @@ namespace QuickMedia } } - sf::Uint32 codePoint = textElement.text[i]; + const unsigned char *cp = (const unsigned char*)&textElement.text[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, textElement.text.size() - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } // TODO: Make this work when combining multiple different fonts (for example latin and japanese). // For japanese we could use a hack, because all japanese characters are monospace (exception being half-width characters). - float kerning = ff->getKerning(prevCodePoint, codePoint, characterSize); - prevCodePoint = codePoint; + // TODO: + float kerning = ff->get_kerning(prevCodePoint, codepoint); + //float kerning = 0.0f; + prevCodePoint = codepoint; glyphPos.x += kerning; - int vertexStart = vertices[vertices_index].getVertexCount(); + int vertexStart = vertices[vertices_index].size(); - switch(codePoint) + i += clen; + switch(codepoint) { case ' ': { - sf::Vector2f vertexTopLeft(glyphPos.x, glyphPos.y - vspace); - sf::Vector2f vertexTopRight(glyphPos.x + hspace, glyphPos.y - vspace); - sf::Vector2f vertexBottomLeft(glyphPos.x, glyphPos.y); - sf::Vector2f vertexBottomRight(glyphPos.x + hspace, glyphPos.y); - - vertices[vertices_index].append({ vertexTopRight, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexTopLeft, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexBottomLeft, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexBottomLeft, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexBottomRight, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexTopRight, sf::Color::Transparent, sf::Vector2f() }); + mgl::vec2f vertexTopLeft(glyphPos.x, glyphPos.y - vspace); + mgl::vec2f vertexTopRight(glyphPos.x + hspace, glyphPos.y - vspace); + mgl::vec2f vertexBottomLeft(glyphPos.x, glyphPos.y); + mgl::vec2f vertexBottomRight(glyphPos.x + hspace, glyphPos.y); + + vertices[vertices_index].emplace_back(vertexTopRight, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexTopLeft, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexBottomLeft, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexBottomLeft, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexBottomRight, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexTopRight, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); glyphPos.x += hspace; - vertices_linear.push_back({vertices_index, vertexStart, 0, codePoint}); - continue; + vertices_linear.push_back({vertices_index, vertexStart, 0, codepoint}); + break; } case '\t': { const float char_width = hspace * TAB_WIDTH; - sf::Vector2f vertexTopLeft(glyphPos.x, glyphPos.y - vspace); - sf::Vector2f vertexTopRight(glyphPos.x + char_width, glyphPos.y - vspace); - sf::Vector2f vertexBottomLeft(glyphPos.x, glyphPos.y); - sf::Vector2f vertexBottomRight(glyphPos.x + char_width, glyphPos.y); - - vertices[vertices_index].append({ vertexTopRight, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexTopLeft, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexBottomLeft, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexBottomLeft, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexBottomRight, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexTopRight, sf::Color::Transparent, sf::Vector2f() }); + mgl::vec2f vertexTopLeft(glyphPos.x, glyphPos.y - vspace); + mgl::vec2f vertexTopRight(glyphPos.x + char_width, glyphPos.y - vspace); + mgl::vec2f vertexBottomLeft(glyphPos.x, glyphPos.y); + mgl::vec2f vertexBottomRight(glyphPos.x + char_width, glyphPos.y); + + vertices[vertices_index].emplace_back(vertexTopRight, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexTopLeft, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexBottomLeft, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexBottomLeft, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexBottomRight, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexTopRight, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); glyphPos.x += char_width; - vertices_linear.push_back({vertices_index, vertexStart, 0, codePoint}); - continue; + vertices_linear.push_back({vertices_index, vertexStart, 0, codepoint}); + break; } case '\n': { - sf::Vector2f vertexTopLeft(glyphPos.x, glyphPos.y - vspace); - sf::Vector2f vertexTopRight(glyphPos.x, glyphPos.y - vspace); - sf::Vector2f vertexBottomLeft(glyphPos.x, glyphPos.y); - sf::Vector2f vertexBottomRight(glyphPos.x, glyphPos.y); - - vertices[vertices_index].append({ vertexTopRight, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexTopLeft, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexBottomLeft, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexBottomLeft, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexBottomRight, sf::Color::Transparent, sf::Vector2f() }); - vertices[vertices_index].append({ vertexTopRight, sf::Color::Transparent, sf::Vector2f() }); + mgl::vec2f vertexTopLeft(glyphPos.x, glyphPos.y - vspace); + mgl::vec2f vertexTopRight(glyphPos.x, glyphPos.y - vspace); + mgl::vec2f vertexBottomLeft(glyphPos.x, glyphPos.y); + mgl::vec2f vertexBottomRight(glyphPos.x, glyphPos.y); + + vertices[vertices_index].emplace_back(vertexTopRight, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexTopLeft, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexBottomLeft, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexBottomLeft, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexBottomRight, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); + vertices[vertices_index].emplace_back(vertexTopRight, mgl::vec2f(), mgl::Color(0, 0, 0, 0)); glyphPos.x = 0.0f; glyphPos.y += floor(vspace + lineSpacing); - vertices_linear.push_back({vertices_index, vertexStart, 0, codePoint}); - continue; + vertices_linear.push_back({vertices_index, vertexStart, 0, codepoint}); + break; } - } + default: { + mgl::FontGlyph glyph = ff->get_glyph(codepoint); - const sf::Glyph &glyph = ff->getGlyph(codePoint, characterSize, false); - - sf::Vector2f vertexTopLeft(glyphPos.x + glyph.bounds.left, glyphPos.y + glyph.bounds.top); - sf::Vector2f vertexTopRight(glyphPos.x + glyph.bounds.left + glyph.bounds.width, glyphPos.y + glyph.bounds.top); - sf::Vector2f vertexBottomLeft(glyphPos.x + glyph.bounds.left, glyphPos.y + glyph.bounds.top + glyph.bounds.height); - sf::Vector2f vertexBottomRight(glyphPos.x + glyph.bounds.left + glyph.bounds.width, glyphPos.y + glyph.bounds.top + glyph.bounds.height); - - sf::Vector2f textureTopLeft(glyph.textureRect.left, glyph.textureRect.top); - sf::Vector2f textureTopRight(glyph.textureRect.left + glyph.textureRect.width, glyph.textureRect.top); - sf::Vector2f textureBottomLeft(glyph.textureRect.left, glyph.textureRect.top + glyph.textureRect.height); - sf::Vector2f textureBottomRight(glyph.textureRect.left + glyph.textureRect.width, glyph.textureRect.top + glyph.textureRect.height); - - vertices[vertices_index].append({ vertexTopRight, text_color, textureTopRight }); - vertices[vertices_index].append({ vertexTopLeft, text_color, textureTopLeft }); - vertices[vertices_index].append({ vertexBottomLeft, text_color, textureBottomLeft }); - vertices[vertices_index].append({ vertexBottomLeft, text_color, textureBottomLeft }); - vertices[vertices_index].append({ vertexBottomRight, text_color, textureBottomRight }); - vertices[vertices_index].append({ vertexTopRight, text_color, textureTopRight }); - - glyphPos.x += glyph.advance + characterSpacing; - vertices_linear.push_back({vertices_index, vertexStart, 0, codePoint}); + mgl::vec2f vertexTopLeft(glyphPos.x + glyph.position.x, glyphPos.y + glyph.position.y); + mgl::vec2f vertexTopRight(glyphPos.x + glyph.position.x + glyph.size.x, glyphPos.y + glyph.position.y); + mgl::vec2f vertexBottomLeft(glyphPos.x + glyph.position.x, glyphPos.y + glyph.position.y + glyph.size.y); + mgl::vec2f vertexBottomRight(glyphPos.x + glyph.position.x + glyph.size.x, glyphPos.y + glyph.position.y + glyph.size.y); + + mgl::vec2f textureTopLeft(glyph.texture_position.x, glyph.texture_position.y); + mgl::vec2f textureTopRight(glyph.texture_position.x + glyph.texture_size.x, glyph.texture_position.y); + mgl::vec2f textureBottomLeft(glyph.texture_position.x, glyph.texture_position.y + glyph.texture_size.y); + mgl::vec2f textureBottomRight(glyph.texture_position.x + glyph.texture_size.x, glyph.texture_position.y + glyph.texture_size.y); + + vertices[vertices_index].emplace_back(vertexTopRight, textureTopRight, text_color); + vertices[vertices_index].emplace_back(vertexTopLeft, textureTopLeft, text_color); + vertices[vertices_index].emplace_back(vertexBottomLeft, textureBottomLeft, text_color); + vertices[vertices_index].emplace_back(vertexBottomLeft, textureBottomLeft, text_color); + vertices[vertices_index].emplace_back(vertexBottomRight, textureBottomRight, text_color); + vertices[vertices_index].emplace_back(vertexTopRight, textureTopRight, text_color); + + glyphPos.x += glyph.advance + characterSpacing; + vertices_linear.push_back({vertices_index, vertexStart, 0, codepoint}); + break; + } + } } } @@ -569,7 +624,7 @@ namespace QuickMedia for(int i = 0; i < (int)vertices_linear.size(); ++i) { VertexRef &vertex_ref = vertices_linear[i]; - sf::Vertex *vertex = &vertices[vertex_ref.vertices_index][vertex_ref.index]; + mgl::Vertex *vertex = &vertices[vertex_ref.vertices_index][vertex_ref.index]; for(int v = 0; v < 6; ++v) { vertex[v].position.x -= text_wrap_offset; vertex[v].position.y += text_offset_y; @@ -598,7 +653,7 @@ namespace QuickMedia float vertex_left_side = get_text_quad_left_side(vertices_linear[last_space_index + 1]); for(int j = last_space_index + 1; j <= i; ++j) { VertexRef &vertex_ref_wrap = vertices_linear[j]; - sf::Vertex *vertex = &vertices[vertex_ref_wrap.vertices_index][vertex_ref_wrap.index]; + mgl::Vertex *vertex = &vertices[vertex_ref_wrap.vertices_index][vertex_ref_wrap.index]; for(int v = 0; v < 6; ++v) { vertex[v].position.x -= vertex_left_side; vertex[v].position.y += line_height; @@ -621,24 +676,23 @@ namespace QuickMedia } } - boundingBox.width = 0.0f; + boundingBox.size.x = 0.0f; for(VertexRef &vertex_ref : vertices_linear) { - boundingBox.width = std::max(boundingBox.width, get_text_quad_right_side(vertex_ref)); + boundingBox.size.x = std::max(boundingBox.size.x, get_text_quad_right_side(vertex_ref)); } - boundingBox.height = num_lines * line_height; + boundingBox.size.y = num_lines * line_height; // TODO: Clear |vertices| somehow even with editable text for(size_t i = 0; i < FONT_ARRAY_SIZE; ++i) { - vertex_buffers[i].create(vertices[i].getVertexCount()); - if(vertices[i].getVertexCount() > 0) - vertex_buffers[i].update(&vertices[i][0], vertices[i].getVertexCount(), 0); + // TODO: Use VertexBuffer::Dynamic for editable text? + vertex_buffers[i].update(vertices[i].data(), vertices[i].size(), mgl::PrimitiveType::Triangles, mgl::VertexBuffer::Static); } //url_ranges.clear(); if(!editable) { for(size_t i = 0; i < FONT_ARRAY_SIZE; ++i) { vertices[i].clear(); - vertices[i].resize(0); + vertices[i].shrink_to_fit(); } vertices_linear.clear(); vertices_linear.shrink_to_fit(); @@ -649,17 +703,17 @@ namespace QuickMedia { assert(!dirty && !dirtyText); - sf::Font *latin_font; + mgl::Font *latin_font; if(bold_font) - latin_font = FontLoader::get_font(FontLoader::FontType::LATIN_BOLD); + latin_font = FontLoader::get_font(FontLoader::FontType::LATIN_BOLD, characterSize); else - latin_font = FontLoader::get_font(FontLoader::FontType::LATIN); + latin_font = FontLoader::get_font(FontLoader::FontType::LATIN, characterSize); const float vspace = font_get_real_height(latin_font); if(vertices_linear.empty()) { caretIndex = 0; - caretPosition = sf::Vector2f(0.0f, floor(vspace)); + caretPosition = mgl::vec2f(0.0f, floor(vspace)); caret_offset_x = 0.0f; return; } @@ -749,7 +803,7 @@ namespace QuickMedia return num_vertices; } - static bool is_special_character(sf::Uint32 codepoint) { + static bool is_special_character(uint32_t codepoint) { return (codepoint <= 47) || (codepoint >= 58 && codepoint <= 64) || (codepoint >= 91 && codepoint <= 96) || (codepoint >= 123 && codepoint <= 127); } @@ -817,18 +871,56 @@ namespace QuickMedia return startIndex; } + // TODO: Optimize + size_t Text::get_string_index_from_caret_index(size_t caret_index) const { + size_t codepoint_index = 0; + for(size_t i = 0; i < str.size();) { + if(codepoint_index == caret_index) + return i; + + unsigned char *cp = (unsigned char*)&str[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, str.size() - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + + i += clen; + ++codepoint_index; + } + return str.size(); + } + + static size_t utf8_get_length(const std::string &str) { + size_t codepoint_index = 0; + for(size_t i = 0; i < str.size();) { + unsigned char *cp = (unsigned char*)&str[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, str.size() - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + + i += clen; + ++codepoint_index; + } + return codepoint_index; + } + // TODO: Optimize text editing by only processing the changed parts in updateGeometry. // TODO: Split text into lines and add to vertices list so the lines that are cut off are not visible. This is good when using the text and as text input // where there are a max number of rows shown at a time. - void Text::processEvent(const sf::Event &event) + void Text::processEvent(mgl::Window &window, const mgl::Event &event) { if(!editable) return; bool caretAtEnd = caretIndex == (int)vertices_linear.size(); - if(event.type == sf::Event::KeyPressed) + if(event.type == mgl::Event::KeyPressed) { - if(event.key.code == sf::Keyboard::Left && caretIndex > 0) + if(event.key.code == mgl::Keyboard::Left && caretIndex > 0) { if(event.key.control) caretMoveDirection = CaretMoveDirection::LEFT_WORD; @@ -836,7 +928,7 @@ namespace QuickMedia caretMoveDirection = CaretMoveDirection::LEFT; dirtyCaret = true; } - else if(event.key.code == sf::Keyboard::Right && !caretAtEnd) + else if(event.key.code == mgl::Keyboard::Right && !caretAtEnd) { if(event.key.control) caretMoveDirection = CaretMoveDirection::RIGHT_WORD; @@ -844,48 +936,60 @@ namespace QuickMedia caretMoveDirection = CaretMoveDirection::RIGHT; dirtyCaret = true; } - else if(event.key.code == sf::Keyboard::BackSpace && caretIndex > 0) + else if(event.key.code == mgl::Keyboard::Backspace && caretIndex > 0) { - str.erase(caretIndex - 1, 1); - --caretIndex; - dirty = true; - dirtyText = true; - dirtyCaret = true; + const size_t str_index = get_string_index_from_caret_index(caretIndex); + if(str_index > 0) { + const size_t codepoint_start = mgl::utf8_get_start_of_codepoint((const unsigned char*)str.c_str(), str.size(), str_index - 1); + str.erase(codepoint_start, str_index - codepoint_start); + --caretIndex; + dirty = true; + dirtyText = true; + dirtyCaret = true; + } } - else if(event.key.code == sf::Keyboard::Delete && !caretAtEnd) + else if(event.key.code == mgl::Keyboard::Delete && !caretAtEnd) { - str.erase(caretIndex, 1); + const size_t str_index = get_string_index_from_caret_index(caretIndex); + uint32_t decoded_codepoint = 0; + size_t decoded_length = 0; + mgl::utf8_decode((const unsigned char*)str.c_str() + str_index, str.size() - str_index, &decoded_codepoint, &decoded_length); + str.erase(str_index, decoded_length); dirty = true; dirtyText = true; } - else if(event.key.code == sf::Keyboard::D && event.key.control) + else if(event.key.code == mgl::Keyboard::D && event.key.control) { setString(""); } - else if(event.key.code == sf::Keyboard::Up) + else if(event.key.code == mgl::Keyboard::Up) { caretMoveDirection = CaretMoveDirection::UP; } - else if(event.key.code == sf::Keyboard::Down) + else if(event.key.code == mgl::Keyboard::Down) { caretMoveDirection = CaretMoveDirection::DOWN; } - else if(event.key.code == sf::Keyboard::Home) + else if(event.key.code == mgl::Keyboard::Home) { caretMoveDirection = CaretMoveDirection::HOME; } - else if(event.key.code == sf::Keyboard::End) + else if(event.key.code == mgl::Keyboard::End) { caretMoveDirection = CaretMoveDirection::END; } - else if(event.key.code == sf::Keyboard::Enter) + else if(event.key.code == mgl::Keyboard::Enter) { if(event.key.shift && !single_line_edit) { - if(caretAtEnd) + if(caretAtEnd) { str += '\n'; - else - str.insert(caretIndex, '\n'); + } else { + const size_t str_index = get_string_index_from_caret_index(caretIndex); + if(str_index > 0) { + str.insert(str_index, 1, '\n'); + } + } ++caretIndex; dirty = true; @@ -894,34 +998,38 @@ namespace QuickMedia } } } - else if(event.type == sf::Event::TextEntered) + else if(event.type == mgl::Event::TextEntered) { - if(event.text.unicode == 8 || event.text.unicode == 127) // backspace, del + if(event.text.codepoint == 8 || event.text.codepoint == 127) // backspace, del return; - sf::String stringToAdd; - if(event.text.unicode == 22) // ctrl+v + std::string stringToAdd; + if(event.text.codepoint == 22) // ctrl+v { - stringToAdd = sf::Clipboard::getString(); + stringToAdd = window.get_clipboard(); } - else if(event.text.unicode >= 32 || (event.text.unicode == '\t' && !single_line_edit)) - stringToAdd = event.text.unicode; + else if(event.text.codepoint >= 32 || (event.text.codepoint == '\t' && !single_line_edit)) + stringToAdd.assign(event.text.str, event.text.size); else return; - if(caretAtEnd) + if(caretAtEnd) { str += stringToAdd; - else - str.insert(caretIndex, stringToAdd); + } else { + const size_t str_index = get_string_index_from_caret_index(caretIndex); + if(str_index > 0 && str_index != std::string::npos) { + str.insert(str_index, stringToAdd); + } + } - caretIndex += stringToAdd.getSize(); + caretIndex += utf8_get_length(stringToAdd); dirty = true; dirtyText = true; dirtyCaret = true; } } - bool Text::draw(sf::RenderTarget &target) + bool Text::draw(mgl::Window &target) { updateGeometry(); @@ -931,35 +1039,34 @@ namespace QuickMedia caretMoveDirection = CaretMoveDirection::NONE; } - sf::Vector2f pos = position; + mgl::vec2f pos = position; FontLoader::FontType latin_font_type; if(bold_font) latin_font_type = FontLoader::FontType::LATIN_BOLD; else latin_font_type = FontLoader::FontType::LATIN; - sf::Font *latin_font = FontLoader::get_font(latin_font_type); + mgl::Font *latin_font = FontLoader::get_font(latin_font_type, characterSize); const float vspace = font_get_real_height(latin_font); pos.y += floor(vspace); // Origin is at bottom left, we want it to be at top left const FontLoader::FontType font_types[] = { latin_font_type, FontLoader::FontType::CJK, FontLoader::FontType::SYMBOLS }; for(size_t i = 0; i < FONT_INDEX_EMOJI; ++i) { - if(vertex_buffers[i].getVertexCount() == 0) + if(vertex_buffers[i].size() == 0) continue; - sf::Font *font = FontLoader::get_font(font_types[i]); - sf::RenderStates states; - states.transform.translate(pos); - states.texture = &font->getTexture(characterSize); - target.draw(vertex_buffers[i], states); + mgl::Font *font = FontLoader::get_font(font_types[i], characterSize); + mgl::Texture font_texture = font->get_texture(); + vertex_buffers[i].set_texture(&font_texture); + vertex_buffers[i].set_position(pos); + target.draw(vertex_buffers[i]); } - if(vertex_buffers[FONT_INDEX_EMOJI].getVertexCount() > 0) { - sf::RenderStates states; - states.transform.translate(pos); - states.texture = TextureLoader::get_texture("images/emoji.png"); - target.draw(vertex_buffers[FONT_INDEX_EMOJI], states); + if(vertex_buffers[FONT_INDEX_EMOJI].size() > 0) { + vertex_buffers[FONT_INDEX_EMOJI].set_texture(TextureLoader::get_texture("images/emoji.png", true)); + vertex_buffers[FONT_INDEX_EMOJI].set_position(pos); + target.draw(vertex_buffers[FONT_INDEX_EMOJI]); } if(!editable) return true; @@ -967,8 +1074,11 @@ namespace QuickMedia const float caret_margin = std::floor(2.0f * get_config().scale); - sf::RectangleShape caretRect(sf::Vector2f(std::floor(2.0f * get_config().scale), floor(vspace - caret_margin * 2.0f))); - caretRect.setPosition(floor(pos.x + caretPosition.x), floor(pos.y + caretPosition.y + caret_margin + std::floor(4.0f * get_config().scale))); + mgl::Rectangle caretRect(mgl::vec2f(0.0f, 0.0f), mgl::vec2f(std::floor(2.0f * get_config().scale), floor(vspace - caret_margin * 2.0f))); + caretRect.set_position(mgl::vec2f( + floor(pos.x + caretPosition.x), + floor(pos.y + caretPosition.y + caret_margin + std::floor(4.0f * get_config().scale)) + )); target.draw(caretRect); return true; } diff --git a/src/Theme.cpp b/src/Theme.cpp index 90e4b30..36c8ff7 100644 --- a/src/Theme.cpp +++ b/src/Theme.cpp @@ -32,7 +32,7 @@ namespace QuickMedia { return -1; } - static void parse_hex_set_color(const Json::Value &json_obj, const char *field_name, sf::Color &color) { + static void parse_hex_set_color(const Json::Value &json_obj, const char *field_name, mgl::Color &color) { const Json::Value &json_val = json_obj[field_name]; if(!json_val.isString()) { fprintf(stderr, "Warning: theme variable \"%s\" does not exists or is not a string\n", field_name); @@ -52,7 +52,7 @@ namespace QuickMedia { return; } - sf::Color new_color; + mgl::Color new_color; for(int i = 1; i < color_str_len; i += 2) { const int c1 = get_hex_value(color_str[i + 0]); const int c2 = get_hex_value(color_str[i + 1]); diff --git a/src/Utils.cpp b/src/Utils.cpp index d466bee..ca153ab 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -85,7 +85,7 @@ namespace QuickMedia { return (int64_t)time.tv_sec * 1000 + (int64_t)time.tv_nsec / 1000000; } - sf::Vector2f vec2f_floor(float x, float y) { - return sf::Vector2f(int(x), int(y)); + mgl::vec2f vec2f_floor(float x, float y) { + return mgl::vec2f(int(x), int(y)); } } diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp index 8020c3c..f9ae04d 100644 --- a/src/VideoPlayer.cpp +++ b/src/VideoPlayer.cpp @@ -16,11 +16,11 @@ #include #include -const int RETRY_TIME_MS = 500; -const int MAX_RETRIES_CONNECT = 1000; -const int READ_TIMEOUT_MS = 200; - namespace QuickMedia { + static const double RETRY_TIME_SEC = 0.5; + static const int MAX_RETRIES_CONNECT = 1000; + static const double READ_TIMEOUT_SEC = 0.2; + static std::string media_chapters_to_ffmetadata_chapters(const std::vector &chapters) { std::string result = ";FFMETADATA1\n\n"; for(size_t i = 0; i < chapters.size(); ++i) { @@ -126,7 +126,7 @@ namespace QuickMedia { return path; } - VideoPlayer::Error VideoPlayer::launch_video_process(const char *path, const char *audio_path, sf::WindowHandle _parent_window, const std::string &title, const std::string &start_time) { + VideoPlayer::Error VideoPlayer::launch_video_process(const char *path, const char *audio_path, mgl::WindowHandle _parent_window, const std::string &title, const std::string &start_time) { parent_window = _parent_window; if(!tmpnam(ipc_server_path)) { @@ -259,7 +259,7 @@ namespace QuickMedia { return Error::OK; } - VideoPlayer::Error VideoPlayer::load_video(const char *path, const char *audio_path, sf::WindowHandle _parent_window, bool use_youtube_dl, const std::string &title, const std::string &start_time, const std::vector &chapters) { + VideoPlayer::Error VideoPlayer::load_video(const char *path, const char *audio_path, mgl::WindowHandle _parent_window, bool use_youtube_dl, const std::string &title, const std::string &start_time, const std::vector &chapters) { // This check is to make sure we dont change window that the video belongs to. This is not a usecase we will have so // no need to support it for now at least. assert(parent_window == 0 || parent_window == _parent_window); @@ -326,12 +326,12 @@ namespace QuickMedia { if(find_window_tries == max_retries_find_window) return Error::FAIL_TO_FIND_WINDOW; - if(!connected_to_ipc && retry_timer.getElapsedTime().asMilliseconds() >= RETRY_TIME_MS) { + if(!connected_to_ipc && retry_timer.get_elapsed_time_seconds() >= RETRY_TIME_SEC) { retry_timer.restart(); if(connect(ipc_socket, (struct sockaddr*)&ipc_addr, sizeof(ipc_addr)) == -1) { ++connect_tries; if(connect_tries == MAX_RETRIES_CONNECT) { - fprintf(stderr, "Failed to connect to mpv ipc after %d seconds, last error: %s\n", (RETRY_TIME_MS * MAX_RETRIES_CONNECT)/1000, strerror(errno)); + fprintf(stderr, "Failed to connect to mpv ipc after %d seconds, last error: %s\n", (int)(RETRY_TIME_SEC * MAX_RETRIES_CONNECT), strerror(errno)); return Error::FAIL_TO_CONNECT_TIMEOUT; } } else { @@ -339,14 +339,14 @@ namespace QuickMedia { } } - if(connected_to_ipc && window_handle == 0 && retry_timer.getElapsedTime().asMilliseconds() >= RETRY_TIME_MS) { + if(connected_to_ipc && window_handle == 0 && retry_timer.get_elapsed_time_seconds() >= RETRY_TIME_SEC) { retry_timer.restart(); std::vector child_windows = get_child_window(display, parent_window); size_t num_children = child_windows.size(); if(num_children == 0) { ++find_window_tries; if(find_window_tries == max_retries_find_window) { - fprintf(stderr, "Failed to find mpv window after %d seconds\n", (RETRY_TIME_MS * max_retries_find_window)/1000); + fprintf(stderr, "Failed to find mpv window after %d seconds\n", (int)(RETRY_TIME_SEC * max_retries_find_window)); return Error::FAIL_TO_FIND_WINDOW_TIMEOUT; } } else if(num_children == 1) { @@ -462,7 +462,7 @@ namespace QuickMedia { if(err != Error::OK) return err; - sf::Clock read_timer; + mgl::Clock read_timer; expected_request_id = cmd_request_id; do { err = read_ipc_func(); @@ -471,7 +471,7 @@ namespace QuickMedia { if(response_data_status != ResponseDataStatus::NONE) break; - } while(read_timer.getElapsedTime().asMilliseconds() < READ_TIMEOUT_MS); + } while(read_timer.get_elapsed_time_seconds() < READ_TIMEOUT_SEC); if(response_data_status == ResponseDataStatus::OK) { if(request_response_data.type() == result_type) diff --git a/src/gui/Button.cpp b/src/gui/Button.cpp index e44843d..13bc8c6 100644 --- a/src/gui/Button.cpp +++ b/src/gui/Button.cpp @@ -1,42 +1,43 @@ #include "../../include/gui/Button.hpp" #include "../../include/Theme.hpp" #include "../../include/Config.hpp" -#include -#include +#include +#include +#include #include namespace QuickMedia { - static const float PADDING_Y = 10.0f; + static const float PADDING_Y = 5.0f; - Button::Button(const std::string &label, sf::Font *font, unsigned int character_size, float width, sf::Shader *rounded_rectangle_shader, float scale) : - label(label, *font, character_size * scale), - background(sf::Vector2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().shade_color, rounded_rectangle_shader), + Button::Button(const std::string &label, mgl::Font *font, float width, mgl::Shader *rounded_rectangle_shader, float scale) : + label(label, *font), + background(mgl::vec2f(1.0f, 1.0f), 10.0f * get_config().scale, get_theme().shade_color, rounded_rectangle_shader), scale(scale) { - background.set_size(sf::Vector2f(std::floor(width * scale), get_height())); - set_position(sf::Vector2f(0.0f, 0.0f)); + background.set_size(mgl::vec2f(std::floor(width * scale), get_height())); + set_position(mgl::vec2f(0.0f, 0.0f)); } - ButtonEvent Button::on_event(sf::Event &event) { + ButtonEvent Button::on_event(mgl::Event &event) { ButtonEvent performed_event = BUTTON_EVENT_NONE; - if(event.type == sf::Event::MouseMoved) { - if(sf::FloatRect(background.get_position(), background.get_size()).contains(event.mouseMove.x, event.mouseMove.y)) { + if(event.type == mgl::Event::MouseMoved) { + if(mgl::FloatRect(background.get_position(), background.get_size()).contains(mgl::vec2f(event.mouse_move.x, event.mouse_move.y))) { const int inc = 20; - background.set_color(sf::Color( + background.set_color(mgl::Color( std::min(255, (int)background_color.r + inc), std::min(255, (int)background_color.g + inc), std::min(255, (int)background_color.b + inc))); } else { background.set_color(background_color); } - } else if(event.type == sf::Event::MouseButtonPressed) { - if(event.mouseButton.button == sf::Mouse::Left && sf::FloatRect(background.get_position(), background.get_size()).contains(event.mouseButton.x, event.mouseButton.y)) { + } else if(event.type == mgl::Event::MouseButtonPressed) { + if(event.mouse_button.button == mgl::Mouse::Left && mgl::FloatRect(background.get_position(), background.get_size()).contains(mgl::vec2f(event.mouse_button.x, event.mouse_button.y))) { clicked_inside = true; } else { clicked_inside = false; } - } else if(event.type == sf::Event::MouseButtonReleased) { - if(clicked_inside && event.mouseButton.button == sf::Mouse::Left && sf::FloatRect(background.get_position(), background.get_size()).contains(event.mouseButton.x, event.mouseButton.y)) { + } else if(event.type == mgl::Event::MouseButtonReleased) { + if(clicked_inside && event.mouse_button.button == mgl::Mouse::Left && mgl::FloatRect(background.get_position(), background.get_size()).contains(mgl::vec2f(event.mouse_button.x, event.mouse_button.y))) { performed_event = BUTTON_EVENT_CLICKED; } clicked_inside = false; @@ -44,27 +45,27 @@ namespace QuickMedia { return performed_event; } - void Button::draw(sf::RenderTarget &target) { + void Button::draw(mgl::Window &target) { background.draw(target); target.draw(label); } - void Button::set_background_color(sf::Color color) { + void Button::set_background_color(mgl::Color color) { background_color = color; background.set_color(background_color); } - void Button::set_position(sf::Vector2f pos) { + void Button::set_position(mgl::vec2f pos) { background.set_position(pos); - const auto label_bounds = label.getLocalBounds(); - sf::Vector2f label_pos(pos + background.get_size() * 0.5f - sf::Vector2f(label_bounds.width * 0.5f, label_bounds.height * 0.5f) - sf::Vector2f(0.0f, 5.0f * scale)); + const auto label_bounds = label.get_bounds(); + mgl::vec2f label_pos(pos + background.get_size() * 0.5f - label_bounds.size * 0.5f - mgl::vec2f(0.0f, 5.0f * scale)); label_pos.x = std::floor(label_pos.x); label_pos.y = std::floor(label_pos.y); - label.setPosition(label_pos); + label.set_position(label_pos); } - sf::Vector2f Button::get_position() const { + mgl::vec2f Button::get_position() const { return background.get_position(); } @@ -72,7 +73,7 @@ namespace QuickMedia { return background.get_size().x; } - float Button::get_height() const { - return std::floor((PADDING_Y * 2.0f) * scale + label.getLocalBounds().height); + float Button::get_height() { + return std::floor((PADDING_Y * 2.0f) * scale + label.get_bounds().size.y); } } \ No newline at end of file diff --git a/src/plugins/AniList.cpp b/src/plugins/AniList.cpp index 3559a81..b892229 100644 --- a/src/plugins/AniList.cpp +++ b/src/plugins/AniList.cpp @@ -262,6 +262,7 @@ query ($id: Int, $page: Int, $perPage: Int) { } enum class ThumbnailSize { + SMALLEST, MEDIUM, LARGE }; @@ -275,7 +276,7 @@ query ($id: Int, $page: Int, $perPage: Int) { } // TODO: Somehow get the correct thumbnail size? - static sf::Vector2i thumbnail_size_get_prediced_size(ThumbnailSize thumbnail_size) { + static mgl::vec2i thumbnail_size_get_prediced_size(ThumbnailSize thumbnail_size) { switch(thumbnail_size) { case ThumbnailSize::MEDIUM: return {100, 158}; case ThumbnailSize::LARGE: return {215, 304}; diff --git a/src/plugins/FileManager.cpp b/src/plugins/FileManager.cpp index a92f3c1..59d3a2a 100644 --- a/src/plugins/FileManager.cpp +++ b/src/plugins/FileManager.cpp @@ -116,10 +116,10 @@ namespace QuickMedia { body_item->thumbnail_is_local = true; if(is_regular_file) { body_item->thumbnail_url = get_resource_loader_root_path() + std::string("images/file.png"); - body_item->thumbnail_size = sf::Vector2i(18, 24); + body_item->thumbnail_size = mgl::vec2i(18, 24); } else { body_item->thumbnail_url = get_resource_loader_root_path() + std::string("images/folder.png"); - body_item->thumbnail_size = sf::Vector2i(24, 22); + body_item->thumbnail_size = mgl::vec2i(24, 22); } } diff --git a/src/plugins/Fourchan.cpp b/src/plugins/Fourchan.cpp index 01c8546..c906c4d 100644 --- a/src/plugins/Fourchan.cpp +++ b/src/plugins/Fourchan.cpp @@ -353,11 +353,11 @@ namespace QuickMedia { body_item->thumbnail_url = fourchan_image_url + board_id + "/" + tim_str + "s.jpg"; body_item->url = fourchan_image_url + board_id + "/" + tim_str + ext_str; - sf::Vector2i thumbnail_size(64, 64); + mgl::vec2i thumbnail_size(64, 64); const Json::Value &tn_w = post["tn_w"]; const Json::Value &tn_h = post["tn_h"]; if(tn_w.isNumeric() && tn_h.isNumeric()) - thumbnail_size = sf::Vector2i(tn_w.asInt(), tn_h.asInt()); + thumbnail_size = mgl::vec2i(tn_w.asInt(), tn_h.asInt()); body_item->thumbnail_size = std::move(thumbnail_size); } @@ -439,11 +439,11 @@ namespace QuickMedia { // thumbnails always has .jpg extension even if they are gifs or webm. body_item->thumbnail_url = fourchan_image_url + board_id + "/" + std::to_string(tim.asInt64()) + "s.jpg"; - sf::Vector2i thumbnail_size(64, 64); + mgl::vec2i thumbnail_size(64, 64); const Json::Value &tn_w = thread["tn_w"]; const Json::Value &tn_h = thread["tn_h"]; if(tn_w.isNumeric() && tn_h.isNumeric()) - thumbnail_size = sf::Vector2i(tn_w.asInt() * 0.5, tn_h.asInt() * 0.5); + thumbnail_size = mgl::vec2i(tn_w.asInt() / 2, tn_h.asInt() / 2); body_item->thumbnail_size = std::move(thumbnail_size); } diff --git a/src/plugins/ImageBoard.cpp b/src/plugins/ImageBoard.cpp index b87e4bb..3b7850b 100644 --- a/src/plugins/ImageBoard.cpp +++ b/src/plugins/ImageBoard.cpp @@ -1,9 +1,8 @@ #include "../../plugins/ImageBoard.hpp" -#include namespace QuickMedia { - void ImageBoardThreadPage::copy_to_clipboard(const BodyItem *body_item) const { - sf::Clipboard::setString(sf::String::fromUtf8(body_item->get_description().begin(), body_item->get_description().end())); + void ImageBoardThreadPage::copy_to_clipboard(const BodyItem *body_item) { + set_clipboard(body_item->get_description()); } PluginResult ImageBoardThreadPage::login(const std::string &token, const std::string &pin, std::string &response_msg) { diff --git a/src/plugins/Info.cpp b/src/plugins/Info.cpp index 05efc44..2b520ac 100644 --- a/src/plugins/Info.cpp +++ b/src/plugins/Info.cpp @@ -5,7 +5,6 @@ #include "../../include/Program.hpp" #include "../../include/Notification.hpp" #include "../../include/Storage.hpp" -#include namespace QuickMedia { static const char *REVERSE_IMAGE_SEARCH_URL = "reverse-image-search://"; @@ -50,7 +49,7 @@ namespace QuickMedia { } } - void InfoPage::copy_to_clipboard(const BodyItem *body_item) const { + void InfoPage::copy_to_clipboard(const BodyItem *body_item) { std::string url; if(string_starts_with(body_item->url, REVERSE_IMAGE_SEARCH_URL)) { url = body_item->url.substr(strlen(REVERSE_IMAGE_SEARCH_URL)); @@ -61,7 +60,7 @@ namespace QuickMedia { } if(!url.empty()) - sf::Clipboard::setString(sf::String::fromUtf8(url.begin(), url.end())); + set_clipboard(url); } // static diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index c9d57d4..2689904 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -26,7 +26,7 @@ // Remove older messages (outside screen) to save memory. Reload them when the selected body item is the top/bottom one. namespace QuickMedia { - static const sf::Vector2i thumbnail_max_size(600, 337); + static const mgl::vec2i thumbnail_max_size(600, 337); static const char* SERVICE_NAME = "matrix"; static const char* OTHERS_ROOM_TAG = "tld.name.others"; // Filter without account data. TODO: We include pinned events but limit events to 1. That means if the last event is a pin, @@ -102,17 +102,17 @@ namespace QuickMedia { return std::abs(hash); } - sf::Color user_id_to_color(const std::string &user_id) { + mgl::Color user_id_to_color(const std::string &user_id) { const int num_colors = 8; - const sf::Color colors[num_colors] = { - sf::Color(54, 139, 214), - sf::Color(172, 59, 168), - sf::Color(3, 179, 129), - sf::Color(230, 79, 122), - sf::Color(255, 129, 45), - sf::Color(45, 194, 197), - sf::Color(92, 86, 245), - sf::Color(116, 209, 44) + const mgl::Color colors[num_colors] = { + mgl::Color(54, 139, 214), + mgl::Color(172, 59, 168), + mgl::Color(3, 179, 129), + mgl::Color(230, 79, 122), + mgl::Color(255, 129, 45), + mgl::Color(45, 194, 197), + mgl::Color(92, 86, 245), + mgl::Color(116, 209, 44) }; return colors[color_hash_code(user_id) % num_colors]; } @@ -374,7 +374,7 @@ namespace QuickMedia { body_item->thumbnail_url = room->get_avatar_url(); body_item->userdata = room; // Note: this has to be valid as long as the room list is valid! body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; - body_item->thumbnail_size = sf::Vector2i(32, 32); + body_item->thumbnail_size = mgl::vec2i(32, 32); room->body_item = body_item; room_body_item_by_room[room] = body_item; rooms_page->add_body_item(body_item); @@ -440,7 +440,7 @@ namespace QuickMedia { body_item->url = room_id; body_item->thumbnail_url = invite.room_avatar_url; body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; - body_item->thumbnail_size = sf::Vector2i(32, 32); + body_item->thumbnail_size = mgl::vec2i(32, 32); body_item->set_timestamp(invite.timestamp); invites_page->add_body_item(std::move(body_item)); if(invite.new_invite) { @@ -908,7 +908,7 @@ namespace QuickMedia { if(user_info.avatar_url) body_item->thumbnail_url = user_info.avatar_url.value(); body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; - body_item->thumbnail_size = sf::Vector2i(32, 32); + body_item->thumbnail_size = mgl::vec2i(32, 32); users_body->append_item(std::move(body_item)); } @@ -1040,7 +1040,7 @@ namespace QuickMedia { } body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; - body_item->thumbnail_size = sf::Vector2i(32, 32); + body_item->thumbnail_size = mgl::vec2i(32, 32); body_item->thumbnail_url = notification.room->get_avatar_url(); auto extra_data = std::make_shared(); @@ -1957,7 +1957,7 @@ namespace QuickMedia { } } - static bool message_content_extract_thumbnail_size(const rapidjson::Value &content_json, sf::Vector2i &thumbnail_size) { + static bool message_content_extract_thumbnail_size(const rapidjson::Value &content_json, mgl::vec2i &thumbnail_size) { const rapidjson::Value &info_json = GetMember(content_json, "info"); if(!info_json.IsObject()) return false; @@ -4424,7 +4424,7 @@ namespace QuickMedia { body_item->thumbnail_url = std::move(avatar_url); } body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; - body_item->thumbnail_size = sf::Vector2i(32, 32); + body_item->thumbnail_size = mgl::vec2i(32, 32); result_items.push_back(std::move(body_item)); } @@ -4736,7 +4736,7 @@ namespace QuickMedia { } void Matrix::update() { - sf::Clock timer; + mgl::Clock timer; std::optional> task; while((task = ui_thread_tasks.pop_if_available()) != std::nullopt) { task.value()(); diff --git a/src/plugins/MediaGeneric.cpp b/src/plugins/MediaGeneric.cpp index dd70efc..2b88fdb 100644 --- a/src/plugins/MediaGeneric.cpp +++ b/src/plugins/MediaGeneric.cpp @@ -37,7 +37,7 @@ namespace QuickMedia { } } - static PluginResult fetch_page_results(const std::string &url, const std::string &website_url, const std::vector &text_queries, const std::vector &thumbnail_queries, sf::Vector2i thumbnail_max_size, MediaRelatedCustomHandler *custom_handler, BodyItems &result_items, bool cloudflare_bypass, const std::vector &extra_commands) { + static PluginResult fetch_page_results(const std::string &url, const std::string &website_url, const std::vector &text_queries, const std::vector &thumbnail_queries, mgl::vec2i thumbnail_max_size, MediaRelatedCustomHandler *custom_handler, BodyItems &result_items, bool cloudflare_bypass, const std::vector &extra_commands) { std::vector args = extra_commands; if(!website_url.empty()) args.push_back({ "-H", "referer: " + website_url }); @@ -118,7 +118,7 @@ namespace QuickMedia { } } - MediaGenericSearchPage::MediaGenericSearchPage(Program *program, const char *website_url, sf::Vector2i thumbnail_max_size, bool cloudflare_bypass, std::vector extra_commands) : + MediaGenericSearchPage::MediaGenericSearchPage(Program *program, const char *website_url, mgl::vec2i thumbnail_max_size, bool cloudflare_bypass, std::vector extra_commands) : Page(program), website_url(website_url ? website_url : ""), thumbnail_max_size(thumbnail_max_size), cloudflare_bypass(cloudflare_bypass), extra_commands(std::move(extra_commands)) { if(!this->website_url.empty()) { diff --git a/src/plugins/MyAnimeList.cpp b/src/plugins/MyAnimeList.cpp index a4d1d30..ee5d4fd 100644 --- a/src/plugins/MyAnimeList.cpp +++ b/src/plugins/MyAnimeList.cpp @@ -7,7 +7,7 @@ namespace QuickMedia { // Returns {0, 0} if unknown - static sf::Vector2i thumbnail_url_get_resolution(const std::string &url) { + static mgl::vec2i thumbnail_url_get_resolution(const std::string &url) { const size_t index = url.find("/r/"); if(index == std::string::npos) return {0, 0}; @@ -22,7 +22,7 @@ namespace QuickMedia { if(size_end_index == std::string::npos) return {0, 0}; - sf::Vector2i size; + mgl::vec2i size; if(!to_num(url.c_str() + width_index, (x_index - width_index), size.x) || !to_num(url.c_str() + height_index, (size_end_index - height_index), size.y)) return {0, 0}; diff --git a/src/plugins/NyaaSi.cpp b/src/plugins/NyaaSi.cpp index f4c0560..a110c57 100644 --- a/src/plugins/NyaaSi.cpp +++ b/src/plugins/NyaaSi.cpp @@ -274,10 +274,10 @@ namespace QuickMedia { body_item->set_description(std::move(description)); body_item->url = "https://" + domain + std::move(view_url); if(is_trusted) - body_item->set_title_color(sf::Color(43, 255, 47)); + body_item->set_title_color(mgl::Color(43, 255, 47)); else if(is_remake) - body_item->set_title_color(sf::Color(255, 45, 47)); - body_item->thumbnail_size = sf::Vector2i(80, 28); + body_item->set_title_color(mgl::Color(255, 45, 47)); + body_item->thumbnail_size = mgl::vec2i(80, 28); result_items.push_back(std::move(body_item)); } @@ -457,7 +457,7 @@ namespace QuickMedia { QuickMediaStringView src = quickmedia_html_node_get_attribute_value(node, "src"); if(src.data && item_data->index < item_data->body_items->size()) { (*item_data->body_items)[item_data->index]->thumbnail_url.assign(src.data, src.size); - (*item_data->body_items)[item_data->index]->thumbnail_size = sf::Vector2i(120, 120); + (*item_data->body_items)[item_data->index]->thumbnail_size = mgl::vec2i(120, 120); item_data->index++; } return 0; diff --git a/src/plugins/Page.cpp b/src/plugins/Page.cpp index 6cf3790..4ac2a9f 100644 --- a/src/plugins/Page.cpp +++ b/src/plugins/Page.cpp @@ -3,7 +3,6 @@ #include "../../include/Theme.hpp" #include "../../include/Storage.hpp" #include "../../include/QuickMedia.hpp" -#include #include namespace QuickMedia { @@ -45,7 +44,11 @@ namespace QuickMedia { return program->load_manga_content_storage(service_name, manga_title, manga_url, manga_id); } - void Page::copy_to_clipboard(const BodyItem *body_item) const { + void Page::set_clipboard(const std::string &str) { + program->set_clipboard(str); + } + + void Page::copy_to_clipboard(const BodyItem *body_item) { std::string title = body_item->get_title(); std::string author = body_item->get_author(); std::string description = body_item->get_description(); @@ -65,7 +68,7 @@ namespace QuickMedia { } if(!clipboard.empty()) - sf::Clipboard::setString(sf::String::fromUtf8(clipboard.begin(), clipboard.end())); + program->set_clipboard(clipboard); } PluginResult BookmarksPage::submit(const std::string &title, const std::string &url, std::vector &result_tabs) { diff --git a/src/plugins/Saucenao.cpp b/src/plugins/Saucenao.cpp index b99c028..064bb11 100644 --- a/src/plugins/Saucenao.cpp +++ b/src/plugins/Saucenao.cpp @@ -136,7 +136,7 @@ namespace QuickMedia { QuickMediaStringView image_url = data_src.data ? data_src : src; if(image_url.data && item_data->index < item_data->body_items->size()) { (*item_data->body_items)[item_data->index]->thumbnail_url.assign(image_url.data, image_url.size); - (*item_data->body_items)[item_data->index]->thumbnail_size = sf::Vector2i(150, 147); + (*item_data->body_items)[item_data->index]->thumbnail_size = mgl::vec2i(150, 147); item_data->index++; } return 0; diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index 7a5f0d5..8dabd2d 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -542,7 +542,7 @@ namespace QuickMedia { body_item->url = "https://www.youtube.com/watch?v=" + video_id_str; body_item->thumbnail_url = "https://img.youtube.com/vi/" + video_id_str + "/mqdefault.jpg"; - body_item->thumbnail_size = sf::Vector2i(192, 108); + body_item->thumbnail_size = mgl::vec2i(192, 108); added_videos.insert(video_id_str); return body_item; @@ -606,7 +606,7 @@ namespace QuickMedia { body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; body_item->thumbnail_size.x = thumbnail->width; body_item->thumbnail_size.y = thumbnail->height; - body_item->thumbnail_size = clamp_to_size(body_item->thumbnail_size, sf::Vector2i(136, 136)); + body_item->thumbnail_size = clamp_to_size(body_item->thumbnail_size, mgl::vec2i(136, 136)); } return body_item; } @@ -1140,7 +1140,7 @@ namespace QuickMedia { const Json::Value &author_is_channel_owner_json = comment_renderer_json["authorIsChannelOwner"]; if(author_is_channel_owner_json.isBool() && author_is_channel_owner_json.asBool()) - body_item->set_author_color(sf::Color(150, 255, 150)); + body_item->set_author_color(mgl::Color(150, 255, 150)); std::optional comment = yt_json_get_text(comment_renderer_json, "contentText"); if(comment) @@ -1781,7 +1781,7 @@ namespace QuickMedia { body_item->set_description_color(get_theme().faded_text_color); body_item->url = "https://www.youtube.com/watch?v=" + subscription_entry.video_id; body_item->thumbnail_url = "https://img.youtube.com/vi/" + subscription_entry.video_id + "/mqdefault.jpg"; - body_item->thumbnail_size = sf::Vector2i(192, 108); + body_item->thumbnail_size = mgl::vec2i(192, 108); results.push_back({std::move(body_item), subscription_entry.published}); } return results; diff --git a/src/plugins/youtube/YoutubeMediaProxy.cpp b/src/plugins/youtube/YoutubeMediaProxy.cpp index 4fe6c74..913fb77 100644 --- a/src/plugins/youtube/YoutubeMediaProxy.cpp +++ b/src/plugins/youtube/YoutubeMediaProxy.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -222,7 +223,7 @@ namespace QuickMedia { return 0; int64_t start_range = 0; - if(sscanf(range.c_str(), " bytes=%lld", &start_range) != 1) + if(sscanf(range.c_str(), " bytes=%" PRId64, &start_range) != 1) return 0; return start_range; -- cgit v1.2.3