From 4a7b86829025664f6eeef6fcb5fc0894733f2ad6 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 17 Oct 2020 13:42:31 +0200 Subject: Matrix: make displayname more bright, add circle mask shader for avatar and room thumbnails --- src/AsyncImageLoader.cpp | 1 + src/Body.cpp | 51 ++++++++++++++++++++++++++++-------------------- src/QuickMedia.cpp | 30 ++++++++++++++++++++++------ src/plugins/Matrix.cpp | 9 +++++---- 4 files changed, 60 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp index eaf4564..bfef294 100644 --- a/src/AsyncImageLoader.cpp +++ b/src/AsyncImageLoader.cpp @@ -70,6 +70,7 @@ namespace QuickMedia { return ""; } + // TODO: Run in 5 different threads, and add download_to_file(_cache) to reduce memory usage in each (use -O curl option) bool AsyncImageLoader::load_thumbnail(const std::string &url, bool local, sf::Vector2i resize_target_size, bool use_tor, std::shared_ptr thumbnail_data) { update(); diff --git a/src/Body.cpp b/src/Body.cpp index f6800b8..11692aa 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -2,6 +2,7 @@ #include "../include/QuickMedia.hpp" #include "../include/Scale.hpp" #include "../plugins/Plugin.hpp" +#include #include #include #include @@ -43,6 +44,8 @@ namespace QuickMedia { draw_thumbnails(false), wrap_around(false), line_seperator_color(sf::Color(32, 37, 43, 255)), + body_item_render_callback(nullptr), + thumbnail_mask_shader(nullptr), program(program), selected_item(0), prev_selected_item(0), @@ -179,18 +182,12 @@ namespace QuickMedia { page_scroll = 0.0f; } - // TODO: Optimize with memcpy and changing capacity before loop void Body::prepend_items(BodyItems new_items) { - for(auto &body_item : new_items) { - items.insert(items.begin(), std::move(body_item)); - } + items.insert(items.begin(), std::make_move_iterator(new_items.begin()), std::make_move_iterator(new_items.end())); } - // TODO: Optimize with memcpy and changing capacity before loop void Body::append_items(BodyItems new_items) { - for(auto &body_item : new_items) { - items.push_back(std::move(body_item)); - } + items.insert(items.end(), std::make_move_iterator(new_items.begin()), std::make_move_iterator(new_items.end())); } void Body::insert_item_by_timestamp(std::shared_ptr body_item) { @@ -383,19 +380,13 @@ namespace QuickMedia { if(!item->visible) continue; - update_dirty_state(item.get(), size); - item->last_drawn_time = elapsed_time; - - float item_height = get_item_height(item.get()); - - if((after_pos.y - start_y) + item_height + spacing_y > size.y) - last_item_fully_visible = false; - else - last_fully_visible_item = i; - if(after_pos.y - start_y >= size.y) break; + float item_height = get_item_height(item.get()); + update_dirty_state(item.get(), size); + item->last_drawn_time = elapsed_time; + // This is needed here rather than above the loop, since update_dirty_text cant be called inside scissor because it corrupts the text for some reason glEnable(GL_SCISSOR_TEST); glScissor(scissor_pos.x, (int)window_size.y - (int)scissor_pos.y - (int)scissor_size.y, scissor_size.x, scissor_size.y); @@ -403,6 +394,11 @@ namespace QuickMedia { glDisable(GL_SCISSOR_TEST); after_pos.y += item_height + spacing_y; ++num_visible_items; + + if(after_pos.y - start_y > size.y) + last_item_fully_visible = false; + else + last_fully_visible_item = i; } if(last_fully_visible_item == -1) @@ -576,13 +572,26 @@ namespace QuickMedia { const float width_ratio = height_ratio * image_scale_ratio; image.setScale(width_ratio, height_ratio); image.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y)); - window.draw(image); + if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) + window.draw(image, thumbnail_mask_shader); + else + window.draw(image); text_offset_x += image_padding_x + width_ratio * 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)); } else if(!item->thumbnail_url.empty()) { - image_fallback.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y)); - window.draw(image_fallback); + 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(image_fallback.getSize().x * 0.5f); + circle_shape.setFillColor(sf::Color::White); + circle_shape.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y)); + window.draw(circle_shape); + } else { + image_fallback.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y)); + window.draw(image_fallback); + } text_offset_x += image_padding_x + image_fallback.getSize().x; } } diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index bd4b2d4..a2c936f 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -349,6 +349,11 @@ namespace QuickMedia { abort(); } + if(!circle_mask_shader.loadFromFile(resources_root + "shaders/circle_mask.glsl", sf::Shader::Type::Fragment)) { + fprintf(stderr, "Failed to load %s/shaders/circle_mask.glsl", resources_root.c_str()); + abort(); + } + struct sigaction action; action.sa_handler = sigpipe_handler; sigemptyset(&action.sa_mask); @@ -2896,8 +2901,10 @@ namespace QuickMedia { body_item->thumbnail_url = message->thumbnail_url; else if(!message->url.empty() && message->type == MessageType::IMAGE) body_item->thumbnail_url = message->url; - else + else { body_item->thumbnail_url = message->user->avatar_url; + body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; + } // TODO: Show image thumbnail inline instead of url to image and showing it as the thumbnail of the body item body_item->url = message->url; body_item->author_color = message->user->display_name_color; @@ -2931,6 +2938,7 @@ namespace QuickMedia { messages_tab.body->thumbnail_resize_target_size.y = 337; messages_tab.body->thumbnail_fallback_size.x = 32; messages_tab.body->thumbnail_fallback_size.y = 32; + messages_tab.body->thumbnail_mask_shader = &circle_mask_shader; //messages_tab.body->line_seperator_color = sf::Color::Transparent; messages_tab.text = sf::Text("Messages", *font, tab_text_size); tabs.push_back(std::move(messages_tab)); @@ -2942,6 +2950,7 @@ namespace QuickMedia { //rooms_tab.body->line_seperator_color = sf::Color::Transparent; rooms_tab.body->thumbnail_fallback_size.x = 32; rooms_tab.body->thumbnail_fallback_size.y = 32; + rooms_tab.body->thumbnail_mask_shader = &circle_mask_shader; rooms_tab.text = sf::Text("Rooms", *font, tab_text_size); tabs.push_back(std::move(rooms_tab)); @@ -3182,7 +3191,7 @@ namespace QuickMedia { const float tab_vertical_offset = 10.0f; - sf::Text room_name_text("", *font, 18); + sf::Text room_name_text("", *bold_font, 18); const float room_name_text_height = 20.0f; const float room_name_text_padding_y = 10.0f; const float room_name_total_height = room_name_text_height + room_name_text_padding_y * 2.0f; @@ -3308,6 +3317,7 @@ namespace QuickMedia { auto body_item = BodyItem::create(std::move(room_name)); body_item->thumbnail_url = room->avatar_url; body_item->userdata = room.get(); // Note: this has to be valid as long as the room list is valid! + body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; tabs[ROOMS_TAB_INDEX].body->items.push_back(body_item); body_items_by_room[room] = { body_item, true, 0 }; } @@ -3344,8 +3354,12 @@ namespace QuickMedia { auto body_item = find_body_item_by_event_id(body_items, num_body_items, message->related_event_id); if(body_item) { body_item->set_description(message->body); - if(message->related_event_type == RelatedEventType::REDACTION) + if(message->related_event_type == RelatedEventType::REDACTION) { + body_item->embedded_item = nullptr; + body_item->embedded_item_status = EmbeddedItemStatus::NONE; body_item->thumbnail_url = message->user->avatar_url; + body_item->thumbnail_mask_type = ThumbnailMaskType::NONE; + } it = unreferenced_events.erase(it); } else { ++it; @@ -3366,8 +3380,12 @@ namespace QuickMedia { auto body_item = find_body_item_by_event_id(body_items.data(), body_items.size(), message->related_event_id); if(body_item) { body_item->set_description(message->body); - if(message->related_event_type == RelatedEventType::REDACTION) + if(message->related_event_type == RelatedEventType::REDACTION) { + body_item->embedded_item = nullptr; + body_item->embedded_item_status = EmbeddedItemStatus::NONE; body_item->thumbnail_url = message->user->avatar_url; + body_item->thumbnail_mask_type = ThumbnailMaskType::NONE; + } } else { unreferenced_events.push_back(message); } @@ -3883,10 +3901,10 @@ namespace QuickMedia { 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, room_name_total_height * 0.5f - room_avatar_texture_size.y * 0.5f + 5.0f); - window.draw(room_avatar_sprite); + 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.setPosition(body_pos.x + room_name_text_offset_x, room_name_text_padding_y + 4.0f); window.draw(room_name_text); } diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 1cb2aa5..ea5f86c 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -269,10 +269,11 @@ namespace QuickMedia { for(unsigned char c : user_id) { color = (color * 16777619) ^ c; } - sf::Color result = (sf::Color)color; - result.r = 64 + std::max(0, (int)result.r - 64); - result.g = 64 + std::max(0, (int)result.g - 64); - result.b = 64 + std::max(0, (int)result.b - 64); + sf::Uint8 *col = (sf::Uint8*)&color; + sf::Color result(col[0], col[1], col[2]); + result.r = std::min(255, 80 + (int)result.r); + result.g = std::min(255, 80 + (int)result.g); + result.b = std::min(255, 80 + (int)result.b); result.a = 255; return result; } -- cgit v1.2.3