diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | include/Body.hpp | 4 | ||||
-rw-r--r-- | include/Text.hpp | 2 | ||||
-rw-r--r-- | src/Body.cpp | 132 | ||||
-rw-r--r-- | src/Text.cpp | 24 |
5 files changed, 91 insertions, 74 deletions
@@ -85,4 +85,5 @@ Update 4chan thread in real time, just like 4chan-x. Save the original event message, so when replying for example we can use the original message as the replying to message, rather than our converted "body" text. Remove tidy dependency and use my own html-parser. Add option to sort by other than timestamp for nyaa.si. -Add url preview for matrix (using matrix api, fallback to client url preview (using our own url preview project)).
\ No newline at end of file +Add url preview for matrix (using matrix api, fallback to client url preview (using our own url preview project)). +Cleanup old messages in matrix (from matrix plugin), and instead either save them to disk or refetch them from server when going up to read old messages.
\ No newline at end of file diff --git a/include/Body.hpp b/include/Body.hpp index 47de784..bf5f6aa 100644 --- a/include/Body.hpp +++ b/include/Body.hpp @@ -78,6 +78,7 @@ namespace QuickMedia { sf::Color title_color; sf::Color author_color; void *userdata; // Not managed, should be deallocated by whoever sets this + sf::Int32 last_drawn_time; private: std::string title; std::string description; @@ -157,6 +158,8 @@ namespace QuickMedia { sf::Color line_seperator_color; private: void draw_item(sf::RenderWindow &window, BodyItem *item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress); + void update_dirty_state(BodyItem *body_item, sf::Vector2f size); + void clear_body_item_cache(BodyItem *body_item); private: Program *program; std::unordered_map<std::string, std::shared_ptr<ThumbnailData>> item_thumbnail_textures; @@ -173,5 +176,6 @@ namespace QuickMedia { int num_visible_items; bool last_item_fully_visible; int last_fully_visible_item; + sf::Clock draw_timer; }; }
\ No newline at end of file diff --git a/include/Text.hpp b/include/Text.hpp index 6a4ed9c..7e9dda2 100644 --- a/include/Text.hpp +++ b/include/Text.hpp @@ -139,7 +139,6 @@ namespace QuickMedia bool dirtyText; bool dirtyCaret; bool editable; - bool visible; CaretMoveDirection caretMoveDirection; sf::FloatRect boundingBox; float lineSpacing; @@ -149,7 +148,6 @@ namespace QuickMedia int caretIndex; float caret_offset_x; sf::Vector2f caretPosition; - sf::Clock lastSeenTimer; sf::Vector2u renderTargetSize; std::vector<VertexRef> vertices_linear; // TODO: Use textElements instead diff --git a/src/Body.cpp b/src/Body.cpp index 812840d..08ef690 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -23,7 +23,8 @@ namespace QuickMedia { thumbnail_is_local(false), title_color(sf::Color::White), author_color(sf::Color::White), - userdata(nullptr) + userdata(nullptr), + last_drawn_time(0) { if(!_title.empty()) set_title(std::move(_title)); @@ -58,6 +59,7 @@ namespace QuickMedia { title_color = other.title_color; author_color = other.author_color; userdata = other.userdata; + last_drawn_time = other.last_drawn_time; } Body::Body(Program *program, sf::Font *font, sf::Font *bold_font, sf::Font *cjk_font) : @@ -279,6 +281,8 @@ namespace QuickMedia { sf::Vector2f scissor_size = size; const float start_y = pos.y; + const sf::Int32 elapsed_time = draw_timer.getElapsedTime().asMilliseconds(); + if(thumbnail_resize_target_size.x != 0 && thumbnail_resize_target_size.y != 0) { image_max_height = thumbnail_resize_target_size.y; } @@ -294,11 +298,9 @@ namespace QuickMedia { int num_items = items.size(); if(num_items == 0 || size.y <= 0.0f) { - for(auto it = item_thumbnail_textures.begin(); it != item_thumbnail_textures.end();) { - if(!it->second->referenced) - it = item_thumbnail_textures.erase(it); - else - ++it; + item_thumbnail_textures.clear(); + for(auto &body_item : items) { + clear_body_item_cache(body_item.get()); } return; } @@ -307,41 +309,6 @@ namespace QuickMedia { thumbnail_it.second->referenced = false; } - for(auto &body_item : items) { - if(body_item->dirty) { - body_item->dirty = false; - // TODO: Find a way to optimize fromUtf8 - sf::String str = sf::String::fromUtf8(body_item->get_title().data(), body_item->get_title().data() + body_item->get_title().size()); - if(body_item->title_text) - body_item->title_text->setString(std::move(str)); - else - body_item->title_text = std::make_unique<Text>(std::move(str), font, cjk_font, 16, size.x - 50 - image_padding_x * 2.0f); - body_item->title_text->setFillColor(body_item->title_color); - body_item->title_text->updateGeometry(); - } - - if(body_item->dirty_description) { - body_item->dirty_description = false; - sf::String str = sf::String::fromUtf8(body_item->get_description().data(), body_item->get_description().data() + body_item->get_description().size()); - if(body_item->description_text) - body_item->description_text->setString(std::move(str)); - else - body_item->description_text = std::make_unique<Text>(std::move(str), font, cjk_font, 14, size.x - 50 - image_padding_x * 2.0f); - body_item->description_text->updateGeometry(); - } - - if(body_item->dirty_author) { - body_item->dirty_author = false; - sf::String str = sf::String::fromUtf8(body_item->get_author().data(), body_item->get_author().data() + body_item->get_author().size()); - if(body_item->author_text) - body_item->author_text->setString(std::move(str)); - else - body_item->author_text = std::make_unique<Text>(std::move(str), bold_font, cjk_font, 14, size.x - 50 - image_padding_x * 2.0f); - body_item->author_text->setFillColor(body_item->author_color); - body_item->author_text->updateGeometry(); - } - } - if(prev_selected_item < 0 || prev_selected_item >= (int)items.size()) { prev_selected_item = selected_item; } @@ -384,8 +351,6 @@ namespace QuickMedia { pos.y += page_scroll; sf::Vector2u window_size = window.getSize(); - 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); sf::Vector2f prev_pos = pos; for(int i = selected_item - 1; i >= 0; --i) { @@ -395,13 +360,20 @@ namespace QuickMedia { if(!item->visible) continue; + update_dirty_state(item.get(), size); + float item_height = get_item_height(item.get()); prev_pos.y -= (item_height + spacing_y); if(prev_pos.y + item_height + spacing_y < start_y) break; + 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); draw_item(window, item.get(), prev_pos, size, item_height, i, content_progress); + glDisable(GL_SCISSOR_TEST); ++num_visible_items; } @@ -413,6 +385,8 @@ namespace QuickMedia { if(!item->visible) continue; + update_dirty_state(item.get(), size); + float item_height = get_item_height(item.get()); if((after_pos.y - start_y) + item_height + spacing_y > size.y) @@ -423,7 +397,12 @@ namespace QuickMedia { if(after_pos.y - start_y >= size.y) break; + 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); draw_item(window, item.get(), after_pos, size, item_height, i, content_progress); + glDisable(GL_SCISSOR_TEST); after_pos.y += item_height + spacing_y; ++num_visible_items; } @@ -431,17 +410,76 @@ namespace QuickMedia { if(last_fully_visible_item == -1) last_fully_visible_item = selected_item; - glDisable(GL_SCISSOR_TEST); - for(auto it = item_thumbnail_textures.begin(); it != item_thumbnail_textures.end();) { if(!it->second->referenced) it = item_thumbnail_textures.erase(it); else ++it; } + + // TODO: Only do this for items that are not visible, do not loop all items. + // TODO: Verify if this only runs for items that are not visible, and only once + // TODO: Improve performance! right now it can use up to 5-7% cpu with a lot of items! + for(auto &body_item : items) { + if(elapsed_time - body_item->last_drawn_time >= 1500) { + clear_body_item_cache(body_item.get()); + } + } + } + + void Body::update_dirty_state(BodyItem *body_item, sf::Vector2f size) { + if(body_item->dirty) { + body_item->dirty = false; + // TODO: Find a way to optimize fromUtf8 + sf::String str = sf::String::fromUtf8(body_item->get_title().data(), body_item->get_title().data() + body_item->get_title().size()); + if(body_item->title_text) + body_item->title_text->setString(std::move(str)); + else + body_item->title_text = std::make_unique<Text>(std::move(str), font, cjk_font, 16, size.x - 50 - image_padding_x * 2.0f); + body_item->title_text->setFillColor(body_item->title_color); + body_item->title_text->updateGeometry(); + } + + if(body_item->dirty_description) { + body_item->dirty_description = false; + sf::String str = sf::String::fromUtf8(body_item->get_description().data(), body_item->get_description().data() + body_item->get_description().size()); + if(body_item->description_text) + body_item->description_text->setString(std::move(str)); + else + body_item->description_text = std::make_unique<Text>(std::move(str), font, cjk_font, 14, size.x - 50 - image_padding_x * 2.0f); + body_item->description_text->updateGeometry(); + } + + if(body_item->dirty_author) { + body_item->dirty_author = false; + sf::String str = sf::String::fromUtf8(body_item->get_author().data(), body_item->get_author().data() + body_item->get_author().size()); + if(body_item->author_text) + body_item->author_text->setString(std::move(str)); + else + body_item->author_text = std::make_unique<Text>(std::move(str), bold_font, cjk_font, 14, size.x - 50 - image_padding_x * 2.0f); + body_item->author_text->setFillColor(body_item->author_color); + body_item->author_text->updateGeometry(); + } + } + + void Body::clear_body_item_cache(BodyItem *body_item) { + if(body_item->title_text) { + body_item->title_text.reset(); + body_item->dirty = true; + } + if(body_item->description_text) { + body_item->description_text.reset(); + body_item->dirty_description = true; + } + if(body_item->author_text) { + body_item->author_text.reset(); + body_item->dirty_author = true; + } } void Body::draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size) { + update_dirty_state(item, size); + item->last_drawn_time = draw_timer.getElapsedTime().asMilliseconds(); sf::Vector2u window_size = window.getSize(); glEnable(GL_SCISSOR_TEST); glScissor(pos.x, (int)window_size.y - (int)pos.y - (int)size.y, size.x, size.y); @@ -574,10 +612,10 @@ namespace QuickMedia { float Body::get_item_height(BodyItem *item) { float item_height = 0.0f; - if(!item->get_title().empty()) { + if(item->title_text) { item_height += item->title_text->getHeight() - 2.0f; } - if(!item->get_author().empty()) { + if(item->author_text) { item_height += item->author_text->getHeight() - 2.0f; } if(item->description_text) { diff --git a/src/Text.cpp b/src/Text.cpp index 2165037..e311f14 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -37,7 +37,6 @@ namespace QuickMedia dirtyText(false), dirtyCaret(false), editable(false), - visible(true), caretMoveDirection(CaretMoveDirection::NONE), lineSpacing(0.0f), characterSpacing(0.0f), @@ -707,32 +706,10 @@ namespace QuickMedia } sf::Vector2f pos = position; - - // TODO: Do not use maxWidth here. Max width might be set to 99999 and actual text width might be 200. Text width should be calculated instead - //sf::FloatRect targetRect(0.0f, 0.0f, maxWidth, target.getSize().y); - //sf::FloatRect textRect(pos.x, pos.y, maxWidth, ) - //colRect.contains() - //if(pos.x + maxWidth <= 0.0f || pos.x >= maxWidth || pos.y + totalHeight <= 0.0f || pos.y >= target.getSize().y) return; - renderTargetSize = target.getSize(); - if(pos.y + getHeight() <= 0.0f || pos.y >= renderTargetSize.y) - { - if(!editable && visible && lastSeenTimer.getElapsedTime().asMilliseconds() > 3000) - { - visible = false; - vertices[0].resize(0); - vertices[1].resize(0); - } - return false; - } const float vspace = font->getLineSpacing(characterSize); pos.y += floor(vspace); // Origin is at bottom left, we want it to be at top left - if(!visible) { - visible = true; - updateGeometry(true); - } - const sf::Font *fonts[] = { font, cjk_font }; for(size_t i = 0; i < 2; ++i) { sf::RenderStates states; @@ -740,7 +717,6 @@ namespace QuickMedia states.texture = &fonts[i]->getTexture(characterSize); target.draw(vertices[i], states); } - lastSeenTimer.restart(); if(!editable) return true; pos.y -= floor(vspace * 2.0f); |