aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-09-18 17:03:11 +0200
committerdec05eba <dec05eba@protonmail.com>2021-09-18 17:03:11 +0200
commit63774155016ad581dcf418c94cd2ec84fcf86445 (patch)
treece4a9939d2555dce80792a06d1361b9f5d8b8ec0
parent86d23983d8c9cd75af9c40f038f6b9a1f0b5fbb5 (diff)
Render selected item background as a rectangle on top instead of banding
Limit selected item background position to body content position and size
-rw-r--r--include/Body.hpp18
-rw-r--r--include/RoundedRectangle.hpp5
-rw-r--r--shaders/rounded_rectangle.glsl9
-rw-r--r--shaders/rounded_rectangle_no_shadow.glsl9
-rw-r--r--src/Body.cpp306
-rw-r--r--src/RoundedRectangle.cpp33
6 files changed, 220 insertions, 160 deletions
diff --git a/include/Body.hpp b/include/Body.hpp
index 65645e9..91913b5 100644
--- a/include/Body.hpp
+++ b/include/Body.hpp
@@ -17,6 +17,7 @@ namespace Json {
}
namespace QuickMedia {
+ class ThumbnailData;
using BodyItemRenderCallback = std::function<void(std::shared_ptr<BodyItem> &body_item)>;
// Return true to merge
using BodyItemMergeHandler = std::function<bool(BodyItem *prev_item, BodyItem *this_item)>;
@@ -154,9 +155,10 @@ namespace QuickMedia {
void filter_search_fuzzy_item(const std::string &text, BodyItem *body_item);
void handle_item_render(const sf::Vector2f pos, const float item_width, const float item_height, int item_index);
// Returns the the body total drawn height
- float draw_list_view(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, const int prev_num_visible_items, const Json::Value &content_progress);
+ float draw_list_view(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, const Json::Value &content_progress);
void draw_card_view(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, sf::Vector2u window_size, float scissor_y);
void draw_item(sf::RenderWindow &window, std::shared_ptr<BodyItem> &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 = true, bool merge_with_previous = false);
+ void draw_card_item(sf::RenderWindow &window, std::shared_ptr<BodyItem> &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);
void update_dirty_state(BodyItem *body_item, float width);
void clear_body_item_cache(BodyItem *body_item);
sf::Vector2i get_item_thumbnail_size(BodyItem *item) const;
@@ -183,11 +185,25 @@ namespace QuickMedia {
BOTTOM
};
+ struct RenderItem {
+ std::shared_ptr<BodyItem> body_item;
+ sf::Vector2f pos;
+ sf::Vector2f pos_offset;
+ sf::Vector2f size;
+ float item_height;
+ int item_index;
+ bool merge_with_previous;
+ std::shared_ptr<ThumbnailData> item_thumbnail;
+ };
+
// TODO: Prevent items from being removed when render is in progress. That would invalidate references and cause a crash
BodyItems items;
BodyTheme body_theme;
+ // Items that are rendered in the current frame
+ std::vector<RenderItem> render_items;
+
int selected_item;
int prev_selected_item;
double page_scroll = 0.0;
diff --git a/include/RoundedRectangle.hpp b/include/RoundedRectangle.hpp
index 2106634..96e57fd 100644
--- a/include/RoundedRectangle.hpp
+++ b/include/RoundedRectangle.hpp
@@ -17,8 +17,6 @@ namespace QuickMedia {
void set_color(sf::Color color);
sf::Vector2f get_position() const;
sf::Vector2f get_size() const;
- void set_band(sf::Vector2f pos, sf::Vector2f size);
- void set_band_color(sf::Color color);
void draw(sf::RenderTarget &target);
private:
float radius;
@@ -26,8 +24,5 @@ namespace QuickMedia {
sf::Vector2f size;
sf::Vertex vertices[4];
sf::Shader *rounded_rectangle_shader;
- sf::Vector2f band_pos;
- sf::Vector2f band_size;
- sf::Color band_color;
};
} \ No newline at end of file
diff --git a/shaders/rounded_rectangle.glsl b/shaders/rounded_rectangle.glsl
index 2863584..40babe2 100644
--- a/shaders/rounded_rectangle.glsl
+++ b/shaders/rounded_rectangle.glsl
@@ -1,7 +1,4 @@
uniform float radius;
-uniform vec2 band_pos;
-uniform vec2 band_size;
-uniform vec4 band_color;
uniform vec2 resolution;
float rounded_rect(vec2 coord, vec2 size, float r) {
@@ -16,10 +13,6 @@ void main() {
float rect_dist = rounded_rect(uv - center, size, radius);
float a = clamp(1.0 - smoothstep(0.0, 1.0, rect_dist), 0.0, 1.0);
- // same as: if(uv.x >= band_pos.x && uv.x <= band_pos.x + band_size.x && uv.y >= band_pos.y && uv.y <= band_pos.y + band_size.y)
- vec2 band_blend = step(band_pos, uv) - step(band_pos + band_size, uv);
- vec4 front_color = mix(gl_Color, band_color, band_blend.x*band_blend.y);
float shadow_a = clamp(1.0 - smoothstep(0.0, shadow_offset.x, rect_dist), 0.0, 1.0);
- front_color.a *= a;
- gl_FragColor = mix(front_color, vec4(0.0, 0.0, 0.0, 0.14), clamp(shadow_a - a, 0.0, 1.0));
+ gl_FragColor = mix(vec4(gl_Color.rgb, a), vec4(0.0, 0.0, 0.0, 0.14), clamp(shadow_a - a, 0.0, 1.0));
} \ No newline at end of file
diff --git a/shaders/rounded_rectangle_no_shadow.glsl b/shaders/rounded_rectangle_no_shadow.glsl
index c32f842..b12b35c 100644
--- a/shaders/rounded_rectangle_no_shadow.glsl
+++ b/shaders/rounded_rectangle_no_shadow.glsl
@@ -1,7 +1,4 @@
uniform float radius;
-uniform vec2 band_pos;
-uniform vec2 band_size;
-uniform vec4 band_color;
uniform vec2 resolution;
float rounded_rect(vec2 coord, vec2 size, float r) {
@@ -16,9 +13,5 @@ void main() {
float rect_dist = rounded_rect(uv - center, size, radius);
float a = clamp(1.0 - smoothstep(0.0, 1.0, rect_dist), 0.0, 1.0);
- // same as: if(uv.x >= band_pos.x && uv.x <= band_pos.x + band_size.x && uv.y >= band_pos.y && uv.y <= band_pos.y + band_size.y)
- vec2 band_blend = step(band_pos, uv) - step(band_pos + band_size, uv);
- vec4 front_color = mix(gl_Color, band_color, band_blend.x*band_blend.y);
- front_color.a *= a;
- gl_FragColor = front_color;
+ gl_FragColor = vec4(gl_Color.rgb, a);
} \ No newline at end of file
diff --git a/src/Body.cpp b/src/Body.cpp
index 1b300c5..5509938 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -609,21 +609,17 @@ namespace QuickMedia {
const float scissor_y = pos.y;
pos.y = 0.0f;
- if(!rendering_card_view)
+ if(!rendering_card_view) {
pos.x += body_spacing[body_theme].body_padding_horizontal;
+ size.x = std::max(0.0f, size.x - body_spacing[body_theme].body_padding_horizontal * 2.0f);
+ }
if(attach_side == AttachSide::TOP)
pos.y += body_spacing[body_theme].body_padding_vertical;
- if(!rendering_card_view)
- size.x = std::max(0.0f, size.x - body_spacing[body_theme].body_padding_horizontal * 2.0f);
-
float frame_time = frame_timer.restart().asSeconds();
if(frame_time > 1.0f)
frame_time = 1.0f;
- // TODO: Remove the need for this. This is needed because fps is changed to 20 or 2 when idle. That idle handler should be removed
- //if(frame_time > 0.01666f)
- // frame_time = 0.01666f;
if(selected_item >= (int)items.size())
selected_item = (int)items.size() - 1;
@@ -637,7 +633,6 @@ namespace QuickMedia {
elapsed_time_sec = draw_timer.getElapsedTime().asSeconds();
- const int prev_num_visible_items = num_visible_items;
const bool prev_items_cut_off = top_cut_off || bottom_cut_off;
const int prev_first_visible_item = first_visible_item;
const int prev_last_visible_item = last_visible_item;
@@ -781,7 +776,7 @@ namespace QuickMedia {
if(rendering_card_view) {
draw_card_view(window, pos, size, window_size, scissor_y);
} else {
- body_total_height = draw_list_view(window, pos, size, prev_num_visible_items, content_progress);
+ body_total_height = draw_list_view(window, pos, size, content_progress);
}
window.setView(prev_view);
@@ -1002,16 +997,17 @@ namespace QuickMedia {
}
}
- float Body::draw_list_view(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, const int prev_num_visible_items, const Json::Value &content_progress) {
- const int num_items = items.size();
+ static float clamp(float value, float min, float max) {
+ return std::min(max, std::max(min, value));
+ }
- if(prev_num_visible_items > 0 && render_selected_item_bg && body_theme == BODY_THEME_MINIMAL) {
- item_background.set_position(sf::Vector2f(pos.x, item_background_prev_pos.y));
- item_background.set_size(item_background_prev_size);
- item_background.set_color(get_theme().selected_color);
- item_background.set_band(sf::Vector2f(0.0f, 0.0f), sf::Vector2f(0.0f, 0.0f));
- item_background.draw(window);
- }
+ static sf::Vector2f round(sf::Vector2f vec) {
+ return { std::floor(vec.x), std::floor(vec.y) };
+ }
+
+ float Body::draw_list_view(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, const Json::Value &content_progress) {
+ const int num_items = items.size();
+ const float pos_y_before_scroll = pos.y;
int index = -1;
if(attach_side == AttachSide::TOP) {
@@ -1083,22 +1079,29 @@ namespace QuickMedia {
get_item_height(item.get(), size.x, true, true, merge_with_previous, index);
if(attach_side == AttachSide::BOTTOM)
pos.y -= (item->loaded_height + body_spacing[body_theme].spacing_y);
- //page_scroll += add_height;
-
- //const float top_y_clamped = clamp(pos.y, 0.0f, size.y);
- //const float bottom_y_clamped = std::min(pos.y + item->current_loaded_height, size.y);
-
- //float offset_y = 0.0f;
- //if(pos.y < 0.0f)
- // offset_y = pos.y;
- //else if(pos.y > size.y)
- // offset_y = size.y - pos.y;
+
+ RenderItem render_item;
+ render_item.body_item = item;
+ render_item.pos = pos;
+ render_item.size = size;
+ render_item.item_height = item->loaded_height;
+ render_item.item_index = index;
+ render_item.merge_with_previous = merge_with_previous;
+ render_items.push_back(std::move(render_item));
- //sf::View new_view(sf::FloatRect(0.0f, 0.0f, window_size.x, scissor_y + bottom_y_clamped));
- //new_view.setViewport(sf::FloatRect(0.0f, (scissor_y + top_y_clamped) / (float)window_size.y, 1.0f, (scissor_y + bottom_y_clamped) / (float)window_size.y));
- //window.setView(new_view);
+ {
+ sf::Vector2f item_pos;
+ item_pos.x = std::floor(pos.x);
+ item_pos.y = std::floor(pos.y);
+
+ if(body_theme == BODY_THEME_MODERN_SPACIOUS) {
+ item_background.set_position(item_pos);
+ item_background.set_size(sf::Vector2f(size.x, item->loaded_height));
+ item_background.set_color(get_theme().shade_color);
+ item_background.draw(window);
+ }
+ }
- draw_item(window, item, pos/*sf::Vector2f(pos.x, offset_y)*/, size, item->loaded_height, index, content_progress, true, merge_with_previous);
handle_item_render(pos, size.x, item->loaded_height, index);
++num_visible_items;
@@ -1151,6 +1154,33 @@ namespace QuickMedia {
}
}
+ for(RenderItem &render_item : render_items) {
+ if(render_item.item_index == selected_item) {
+ float offset_y_spacing = -body_spacing[body_theme].spacing_y;
+ if(attach_side == AttachSide::BOTTOM)
+ offset_y_spacing = body_spacing[body_theme].spacing_y;
+
+ if(selected_item_fits_in_body) {
+ item_background.set_position(round(
+ sf::Vector2f(
+ 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 {
+ item_background.set_position(round(item_background_prev_pos));
+ }
+
+ item_background.set_size(item_background_prev_size);
+ item_background.set_color(get_theme().selected_color);
+ item_background.draw(window);
+ break;
+ }
+ }
+
+ for(RenderItem &render_item : render_items) {
+ draw_item(window, render_item.body_item, render_item.pos, render_item.size, render_item.item_height, render_item.item_index, content_progress, true, render_item.merge_with_previous);
+ }
+
+ render_items.clear();
return pos.y - pos_y_start;
}
@@ -1230,95 +1260,25 @@ namespace QuickMedia {
item_height = std::min(card_height, item_height + (item_thumbnail ? card_image_text_padding : 0) + card_padding_y * 2 + 5);
row_max_height = std::max(row_max_height, item_height);
- handle_item_render(pos + pos_offset, card_width, item_height, item_index);
+ RenderItem render_item;
+ render_item.body_item = item;
+ render_item.pos = pos;
+ render_item.pos_offset = pos_offset;
+ render_item.item_height = item_height;
+ render_item.item_index = item_index;
+ 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);
- item_background.set_position(pos + pos_offset);
- item_background.set_size(sf::Vector2f(card_width, item_height));
+ item_background.set_position(round(pos + pos_offset));
+ item_background.set_size(round(sf::Vector2f(card_width, item_height)));
item_background.set_color(get_theme().card_item_background_color);
- item_background.set_band(item_background_prev_pos - (pos + pos_offset), item_background_prev_size);
- item_background.set_band_color(get_theme().selected_color);
item_background.draw(window);
- {
- 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);
- 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_height = new_image_size.y;
- if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) {
- thumbnail_mask_shader->setUniform("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);
- 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);
- 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);
- 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);
- 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);
-
- 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->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->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->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().card_item_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);
- }
- }
+ handle_item_render(pos + pos_offset, card_width, item_height, item_index);
++num_visible_items;
if(first_visible_item == -1 || item_index < first_visible_item)
@@ -1359,6 +1319,29 @@ 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);
+
+ for(RenderItem &render_item : render_items) {
+ if(render_item.item_index == selected_item) {
+ item_background.set_position(round(
+ sf::Vector2f(
+ 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));
+ item_background.set_color(get_theme().selected_color);
+ item_background.draw(window);
+ break;
+ }
+ }
+
+ 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());
+ }
+
+ render_items.clear();
+
if(row_has_selected_item)
item_background_target_size = sf::Vector2f(card_width, row_max_height);
}
@@ -1378,15 +1361,6 @@ namespace QuickMedia {
item_pos.x = std::floor(pos.x);
item_pos.y = std::floor(pos.y);
- if(item_index != -1 && body_theme == BODY_THEME_MODERN_SPACIOUS) {
- item_background.set_size(sf::Vector2f(size.x, item_height));
- item_background.set_position(item_pos);
- item_background.set_color(get_theme().shade_color);
- item_background.set_band(item_background_prev_pos - pos, item_background_prev_size);
- item_background.set_band_color(get_theme().selected_color);
- item_background.draw(window);
- }
-
const float padding_y = item_thumbnail ? body_spacing[body_theme].padding_y : body_spacing[body_theme].padding_y_text_only;
float text_offset_x = body_spacing[body_theme].padding_x;
@@ -1550,6 +1524,92 @@ namespace QuickMedia {
}
}
+ void Body::draw_card_item(sf::RenderWindow &window, std::shared_ptr<BodyItem> &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());
+
+ 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);
+
+ {
+ 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);
+ 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_height = new_image_size.y;
+ if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) {
+ thumbnail_mask_shader->setUniform("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);
+ 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);
+ 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);
+ 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);
+ 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);
+
+ 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->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->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->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().card_item_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);
+ }
+ }
+ }
+
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);
diff --git a/src/RoundedRectangle.cpp b/src/RoundedRectangle.cpp
index 4776618..fc56823 100644
--- a/src/RoundedRectangle.cpp
+++ b/src/RoundedRectangle.cpp
@@ -1,13 +1,17 @@
#include "../include/RoundedRectangle.hpp"
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
+#include <atomic>
#include <assert.h>
namespace QuickMedia {
static const float shadow_radius = 20.0f; // Has to match the shadow offset in rounded_rectangle.glsl
+ static std::atomic<float> cached_radius = 0.0f;
+ static std::atomic<float> cached_resolution_x = 0.0f;
+ static std::atomic<float> cached_resolution_y = 0.0f;
RoundedRectangle::RoundedRectangle(sf::Vector2f size, float radius, sf::Color color, sf::Shader *rounded_rectangle_shader) :
- radius(radius), pos(0.0f, 0.0f), size(size), rounded_rectangle_shader(rounded_rectangle_shader), band_color(sf::Color::Transparent)
+ radius(radius), pos(0.0f, 0.0f), size(size), rounded_rectangle_shader(rounded_rectangle_shader)
{
assert(rounded_rectangle_shader);
set_color(color);
@@ -44,22 +48,21 @@ namespace QuickMedia {
return size;
}
- void RoundedRectangle::set_band(sf::Vector2f pos, sf::Vector2f size) {
- band_pos = pos;
- band_size = size;
- }
-
- void RoundedRectangle::set_band_color(sf::Color color) {
- band_color = color;
- }
-
void RoundedRectangle::draw(sf::RenderTarget &target) {
+ const sf::Vector2f resolution = size + sf::Vector2f(shadow_radius*2.0f, shadow_radius*2.0f);
+
// TODO: Remove these for optimizations. Also do the same in other places where setUniform is called
- rounded_rectangle_shader->setUniform("radius", radius);
- rounded_rectangle_shader->setUniform("band_pos", band_pos + sf::Vector2f(shadow_radius, shadow_radius));
- rounded_rectangle_shader->setUniform("band_size", band_size);
- rounded_rectangle_shader->setUniform("band_color", sf::Glsl::Vec4(band_color.r/255.0f, band_color.g/255.0f, band_color.b/255.0f, band_color.a/255.0f));
- rounded_rectangle_shader->setUniform("resolution", size + sf::Vector2f(shadow_radius*2.0f, shadow_radius*2.0f));
+ if(std::abs(cached_radius - radius) > 0.01f) {
+ rounded_rectangle_shader->setUniform("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));
+ cached_resolution_x = resolution.x;
+ cached_resolution_y = resolution.y;
+ }
+
target.draw(vertices, 4, sf::Quads, rounded_rectangle_shader);
}
} \ No newline at end of file