From 381f449e7153d5305df5ae5218cb6a8dfcf20184 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 11 Sep 2021 00:11:03 +0200 Subject: Add 4chan image zoom/panning --- src/QuickMedia.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 15 deletions(-) (limited to 'src/QuickMedia.cpp') diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 258249b..d91f2a1 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -3821,6 +3821,22 @@ namespace QuickMedia { return true; } + struct ImageControl { + float zoom = 1.0f; + bool pressed = false; + bool moved = false; + sf::Vector2f offset; // relative to center + sf::Vector2i prev_mouse_pos; + }; + + static sf::Vector2f to_vec2f(sf::Vector2i vec) { + return sf::Vector2f(vec.x, vec.y); + } + + static sf::Vector2f to_vec2f(sf::Vector2u vec) { + return sf::Vector2f(vec.x, vec.y); + } + void Program::image_board_thread_page(ImageBoardThreadPage *thread_page, Body *thread_body) { // TODO: Instead of using stage here, use different pages for each stage enum class NavigationStage { @@ -3844,6 +3860,8 @@ namespace QuickMedia { std::string attached_image_url; ImageBoardCaptchaChallenge captcha_challenge; + ImageControl image_control; + captcha_texture.setSmooth(true); captcha_bg_texture.setSmooth(true); @@ -4048,17 +4066,19 @@ namespace QuickMedia { } else { BodyItem *selected_item = thread_body->get_selected(); if(selected_item && !selected_item->url.empty()) { - navigation_stage = NavigationStage::VIEWING_ATTACHED_IMAGE; attached_image_url = selected_item->url; sf::Image image; TaskResult task_result = run_task_with_loading_screen([&attached_image_url, &image]{ - std::string image_data; - if(download_to_string_cache(attached_image_url, image_data, {}) != DownloadResult::OK) { + SHA256 sha256; + sha256.add(attached_image_url.data(), attached_image_url.size()); + Path media_file_path = get_cache_dir().join("media").join(sha256.getHash()); + + if(get_file_type(media_file_path) == FileType::FILE_NOT_FOUND && download_to_file(attached_image_url, media_file_path.data, {}, true) != DownloadResult::OK) { show_notification("QuickMedia", "Failed to download image: " + attached_image_url, Urgency::CRITICAL); return false; } - if(!load_image_from_memory(image, image_data.data(), image_data.size())) { + if(!load_image_from_file(image, media_file_path.data)) { show_notification("QuickMedia", "Failed to load image: " + attached_image_url, Urgency::CRITICAL); return false; } @@ -4070,7 +4090,16 @@ namespace QuickMedia { 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); 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.moved = false; + if(image_control.pressed) + image_control.prev_mouse_pos = sf::Mouse::getPosition(window); } else { show_notification("QuickMedia", "Failed to load image: " + attached_image_url, Urgency::CRITICAL); } @@ -4214,6 +4243,36 @@ namespace QuickMedia { } } + if(navigation_stage == NavigationStage::VIEWING_ATTACHED_IMAGE) { + if(event.type == sf::Event::MouseWheelScrolled) { + image_control.zoom *= (1.0f + event.mouseWheelScroll.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) { + 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.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; + 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) { + 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); + } + } + } + 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) { navigation_stage = NavigationStage::VIEWING_COMMENTS; @@ -4440,17 +4499,25 @@ namespace QuickMedia { window.draw(captcha_solution_text); } else if(navigation_stage == NavigationStage::VIEWING_ATTACHED_IMAGE) { if(attached_image_texture->getNativeHandle() != 0) { - 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 image_scale = get_ratio(texture_size_f, clamp_to_size(texture_size_f, content_size)); - attached_image_sprite.setScale(image_scale); - - auto image_size = texture_size_f; - image_size.x *= image_scale.x; - image_size.y *= image_scale.y; - attached_image_sprite.setPosition(std::floor(content_size.x * 0.5f - image_size.x * 0.5f), std::floor(content_size.y * 0.5f - image_size.y * 0.5f)); - window.draw(attached_image_sprite); + if(image_control.moved) { + attached_image_sprite.setOrigin(image_control.offset); + attached_image_sprite.setScale(image_control.zoom, image_control.zoom); + attached_image_sprite.setPosition(window_size * 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 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); + + auto image_size = texture_size_f; + image_size.x *= image_scale.x; + image_size.y *= image_scale.y; + attached_image_sprite.setPosition(std::floor(content_size.x * 0.5f - image_size.x * 0.5f), std::floor(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); -- cgit v1.2.3