diff options
author | dec05eba <dec05eba@protonmail.com> | 2021-04-21 13:29:01 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2021-04-21 13:29:01 +0200 |
commit | 3ac1120fd40b84507c51f867559bd05adff4eecf (patch) | |
tree | 32a3d7e037dd0fa07f764e563cfaa304470ad7f1 | |
parent | 0f151afa58c1f725a652eaa4444ce3e2b2509770 (diff) |
Use shader for rounded rectangle, improve circle shader
-rw-r--r-- | external/RoundedRectangleShape.cpp | 103 | ||||
-rw-r--r-- | external/RoundedRectangleShape.hpp | 151 | ||||
-rw-r--r-- | include/Body.hpp | 8 | ||||
-rw-r--r-- | include/Entry.hpp | 7 | ||||
-rw-r--r-- | include/QuickMedia.hpp | 1 | ||||
-rw-r--r-- | include/RoundedRectangle.hpp | 27 | ||||
-rw-r--r-- | include/SearchBar.hpp | 8 | ||||
-rw-r--r-- | include/Tabs.hpp | 7 | ||||
-rw-r--r-- | shaders/circle_mask.glsl | 20 | ||||
-rw-r--r-- | shaders/rounded_rectangle.glsl | 15 | ||||
-rw-r--r-- | src/Body.cpp | 29 | ||||
-rw-r--r-- | src/Entry.cpp | 15 | ||||
-rw-r--r-- | src/QuickMedia.cpp | 39 | ||||
-rw-r--r-- | src/RoundedRectangle.cpp | 46 | ||||
-rw-r--r-- | src/SearchBar.cpp | 19 | ||||
-rw-r--r-- | src/Tabs.cpp | 19 |
16 files changed, 179 insertions, 335 deletions
diff --git a/external/RoundedRectangleShape.cpp b/external/RoundedRectangleShape.cpp deleted file mode 100644 index e56cf9f..0000000 --- a/external/RoundedRectangleShape.cpp +++ /dev/null @@ -1,103 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include "RoundedRectangleShape.hpp" -#include <cmath> - -namespace sf -{ -//////////////////////////////////////////////////////////// -RoundedRectangleShape::RoundedRectangleShape(const Vector2f& size, float radius, unsigned int cornerPointCount) -{ - mySize = size; - myRadius = radius; - myCornerPointCount = cornerPointCount; - update(); -} - -//////////////////////////////////////////////////////////// -void RoundedRectangleShape::setSize(const Vector2f& size) -{ - // Modified by dec05eba - if(std::abs(size.x - mySize.x) > 1.0f || std::abs(size.y - mySize.y) > 1.0f) { - mySize = size; - update(); - } -} - -//////////////////////////////////////////////////////////// -const Vector2f& RoundedRectangleShape::getSize() const -{ - return mySize; -} - -//////////////////////////////////////////////////////////// -void RoundedRectangleShape::setCornersRadius(float radius) -{ - myRadius = radius; - update(); -} - -//////////////////////////////////////////////////////////// -float RoundedRectangleShape::getCornersRadius() const -{ - return myRadius; -} - -//////////////////////////////////////////////////////////// -void RoundedRectangleShape::setCornerPointCount(unsigned int count) -{ - myCornerPointCount = count; - update(); -} - -//////////////////////////////////////////////////////////// -std::size_t RoundedRectangleShape::getPointCount() const -{ - return myCornerPointCount*4; -} - -//////////////////////////////////////////////////////////// -sf::Vector2f RoundedRectangleShape::getPoint(std::size_t index) const -{ - if(index >= myCornerPointCount*4) - return sf::Vector2f(0,0); - - float deltaAngle = 90.0f/(myCornerPointCount-1); - sf::Vector2f center; - unsigned int centerIndex = index/myCornerPointCount; - static const float pi = 3.141592654f; - - switch(centerIndex) - { - case 0: center.x = mySize.x - myRadius; center.y = myRadius; break; - case 1: center.x = myRadius; center.y = myRadius; break; - case 2: center.x = myRadius; center.y = mySize.y - myRadius; break; - case 3: center.x = mySize.x - myRadius; center.y = mySize.y - myRadius; break; - } - - return sf::Vector2f(myRadius*cos(deltaAngle*(index-centerIndex)*pi/180)+center.x, - -myRadius*sin(deltaAngle*(index-centerIndex)*pi/180)+center.y); -} -} // namespace sf
\ No newline at end of file diff --git a/external/RoundedRectangleShape.hpp b/external/RoundedRectangleShape.hpp deleted file mode 100644 index ab1c880..0000000 --- a/external/RoundedRectangleShape.hpp +++ /dev/null @@ -1,151 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef ROUNDEDRECTANGLESHAPE_HPP -#define ROUNDEDRECTANGLESHAPE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include <SFML/Graphics/Shape.hpp> - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Specialized shape representing a rectangle -/// with rounded corners -//////////////////////////////////////////////////////////// -class RoundedRectangleShape : public sf::Shape -{ - public: - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// \param size Size of the rectangle - /// \param radius Radius for each rounded corner - /// \param cornerPointCount Number of points of each corner - /// - //////////////////////////////////////////////////////////// - explicit RoundedRectangleShape(const Vector2f& size = Vector2f(0, 0), float radius = 0, unsigned int cornerPointCount = 0); - - //////////////////////////////////////////////////////////// - /// \brief Set the size of the rounded rectangle - /// - /// \param size New size of the rounded rectangle - /// - /// \see getSize - /// - //////////////////////////////////////////////////////////// - void setSize(const Vector2f& size); - - //////////////////////////////////////////////////////////// - /// \brief Get the size of the rounded rectangle - /// - /// \return Size of the rounded rectangle - /// - /// \see setSize - /// - //////////////////////////////////////////////////////////// - const Vector2f& getSize() const; - - //////////////////////////////////////////////////////////// - /// \brief Set the radius of the rounded corners - /// - /// \param radius Radius of the rounded corners - /// - /// \see getCornersRadius - /// - //////////////////////////////////////////////////////////// - void setCornersRadius(float radius); - - //////////////////////////////////////////////////////////// - /// \brief Get the radius of the rounded corners - /// - /// \return Radius of the rounded corners - /// - /// \see setCornersRadius - /// - //////////////////////////////////////////////////////////// - float getCornersRadius() const; - - //////////////////////////////////////////////////////////// - /// \brief Set the number of points of each corner - /// - /// \param count New number of points of the rounded rectangle - /// - /// \see getPointCount - /// - //////////////////////////////////////////////////////////// - void setCornerPointCount(unsigned int count); - - //////////////////////////////////////////////////////////// - /// \brief Get the number of points defining the rounded rectangle - /// - /// \return Number of points of the rounded rectangle - /// - //////////////////////////////////////////////////////////// - virtual std::size_t getPointCount() const; - - //////////////////////////////////////////////////////////// - /// \brief Get a point of the rounded rectangle - /// - /// The result is undefined if \a index is out of the valid range. - /// - /// \param index Index of the point to get, in range [0 .. GetPointCount() - 1] - /// - /// \return Index-th point of the shape - /// - //////////////////////////////////////////////////////////// - virtual sf::Vector2f getPoint(std::size_t index) const; - - private: - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Vector2f mySize; - float myRadius; - unsigned int myCornerPointCount; -}; -} -#endif // ROUNDEDRECTANGLESHAPE_HPP - -//////////////////////////////////////////////////////////// -/// \class sf::RoundedRectangleShape -/// \ingroup graphics -/// -/// This class inherits all the functions of sf::Transformable -/// (position, rotation, scale, bounds, ...) as well as the -/// functions of sf::Shape (outline, color, texture, ...). -/// -/// Usage example: -/// \code -/// sf::RoundedRectangleShape roundedRectangle; -/// rectangle.setSize(sf::Vector2f(100, 50)); -/// rectangle.setCornersRadius(5); -/// rectangle.setOutlineThickness(5); -/// rectangle.setPosition(10, 20); -/// ... -/// window.draw(rectangle); -/// \endcode -/// -/// \see sf::Shape, sf::CircleShape, sf::ConvexShape -/// -////////////////////////////////////////////////////////////
\ No newline at end of file diff --git a/include/Body.hpp b/include/Body.hpp index 98baa6d..58e1414 100644 --- a/include/Body.hpp +++ b/include/Body.hpp @@ -2,10 +2,10 @@ #include "Text.hpp" #include "AsyncImageLoader.hpp" +#include "RoundedRectangle.hpp" #include <SFML/Graphics/Text.hpp> #include <SFML/Graphics/RectangleShape.hpp> #include <SFML/Graphics/Sprite.hpp> -#include "../external/RoundedRectangleShape.hpp" #include <json/value.h> #include <thread> #include <future> @@ -179,7 +179,7 @@ namespace QuickMedia { class Body { public: - Body(Program *program, sf::Texture &loading_icon_texture); + Body(Program *program, sf::Texture &loading_icon_texture, sf::Shader *rounded_rectangle_shader); ~Body(); // Select previous page, ignoring invisible items. Returns true if the item was changed. This can be used to check if the top was hit when wrap_around is set to false @@ -279,7 +279,6 @@ namespace QuickMedia { // TODO: Use a loading gif or something similar instead, to properly indicate the image is loading. Which could also have text that says "failed to load image" when image loading failed. sf::RectangleShape image_fallback; sf::RectangleShape item_separator; - sf::RoundedRectangleShape item_background; sf::Sprite image; sf::Sprite loading_icon; int num_visible_items; @@ -313,6 +312,7 @@ namespace QuickMedia { float selected_scrolled = 0.0f; bool loaded_textures_changed = false; std::shared_ptr<BodyItem> clicked_body_item = nullptr; - //float scroll_y = 0.0f; + RoundedRectangle item_background; + RoundedRectangle reaction_background; }; }
\ No newline at end of file diff --git a/include/Entry.hpp b/include/Entry.hpp index 10210f8..02d0a59 100644 --- a/include/Entry.hpp +++ b/include/Entry.hpp @@ -1,7 +1,7 @@ #pragma once #include "Text.hpp" -#include "../external/RoundedRectangleShape.hpp" +#include "RoundedRectangle.hpp" #include <SFML/Graphics/Text.hpp> #include <functional> @@ -9,6 +9,7 @@ namespace sf { class Font; class Event; class RenderWindow; + class Shader; } namespace QuickMedia { @@ -17,7 +18,7 @@ namespace QuickMedia { class Entry { public: - Entry(const std::string &placeholder_text); + Entry(const std::string &placeholder_text, sf::Shader *rounded_rectangle_shader); void process_event(sf::Event &event); void draw(sf::RenderWindow &window); @@ -35,7 +36,7 @@ namespace QuickMedia { private: Text text; float width; - sf::RoundedRectangleShape background; + RoundedRectangle background; sf::Text placeholder; bool mouse_left_inside; }; diff --git a/include/QuickMedia.hpp b/include/QuickMedia.hpp index e61c2ff..ec788bf 100644 --- a/include/QuickMedia.hpp +++ b/include/QuickMedia.hpp @@ -173,6 +173,7 @@ namespace QuickMedia { int exit_code = 0; std::string resources_root; sf::Shader circle_mask_shader; + sf::Shader rounded_rectangle_shader; bool no_video = false; bool force_no_video = false; bool use_system_mpv_config = false; diff --git a/include/RoundedRectangle.hpp b/include/RoundedRectangle.hpp new file mode 100644 index 0000000..f72a083 --- /dev/null +++ b/include/RoundedRectangle.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include <SFML/System/Vector2.hpp> +#include <SFML/Graphics/Vertex.hpp> + +namespace sf { + class RenderWindow; + class Shader; +} + +namespace QuickMedia { + class RoundedRectangle { + public: + RoundedRectangle(sf::Vector2f size, float radius, sf::Color color, sf::Shader *rounded_rectangle_shader); + void set_position(sf::Vector2f pos); + void set_size(sf::Vector2f size); + sf::Vector2f get_position() const; + sf::Vector2f get_size() const; + void draw(sf::RenderWindow &window); + private: + float radius; + sf::Vector2f pos; + sf::Vector2f size; + sf::Vertex vertices[4]; + sf::Shader *rounded_rectangle_shader; + }; +}
\ No newline at end of file diff --git a/include/SearchBar.hpp b/include/SearchBar.hpp index b2cdf4d..76ad24b 100644 --- a/include/SearchBar.hpp +++ b/include/SearchBar.hpp @@ -1,16 +1,17 @@ #pragma once +#include "RoundedRectangle.hpp" #include <SFML/Graphics/Text.hpp> #include <SFML/Graphics/RectangleShape.hpp> #include <SFML/Graphics/Sprite.hpp> #include <SFML/System/Clock.hpp> -#include "../external/RoundedRectangleShape.hpp" #include <functional> namespace sf { class Font; class RenderWindow; class Event; + class Shader; } namespace QuickMedia { @@ -21,7 +22,7 @@ namespace QuickMedia { class SearchBar { public: - SearchBar(sf::Texture *plugin_logo, const std::string &placeholder, bool input_masked = false); + SearchBar(sf::Texture *plugin_logo, sf::Shader *rounded_rectangle_shader, const std::string &placeholder, bool input_masked = false); void draw(sf::RenderWindow &window, bool draw_shadow = true); void on_event(sf::Event &event); void update(); @@ -32,7 +33,6 @@ namespace QuickMedia { void set_to_autocomplete(); void set_autocomplete_text(const std::string &text); void set_vertical_position(float vertical_pos); - void set_background_color(sf::Color color); float getBottom() const; float getBottomWithoutShadow() const; @@ -53,7 +53,7 @@ namespace QuickMedia { private: sf::Text text; sf::Text autocomplete_text; - sf::RoundedRectangleShape background; + RoundedRectangle background; sf::RectangleShape background_shadow; sf::RectangleShape shade; sf::RectangleShape caret; diff --git a/include/Tabs.hpp b/include/Tabs.hpp index d5aa5b6..d899a61 100644 --- a/include/Tabs.hpp +++ b/include/Tabs.hpp @@ -1,6 +1,6 @@ #pragma once -#include "../external/RoundedRectangleShape.hpp" +#include "RoundedRectangle.hpp" #include <SFML/Graphics/RectangleShape.hpp> #include <SFML/Graphics/Text.hpp> #include <vector> @@ -9,12 +9,13 @@ namespace sf { class Event; class RenderWindow; + class Shader; } namespace QuickMedia { class Tabs { public: - Tabs(sf::Color shade_color = sf::Color(33, 37, 44)); + Tabs(sf::Shader *rounded_rectangle_shader, sf::Color shade_color = sf::Color(33, 37, 44)); static float get_height(); static float get_shade_height(); @@ -34,7 +35,7 @@ namespace QuickMedia { float tab_index_to_x_offset(int index); private: std::vector<sf::Text> tab_texts; - sf::RoundedRectangleShape background; + RoundedRectangle background; sf::RectangleShape shade; int selected_tab = 0; float scroll = 0.0f; diff --git a/shaders/circle_mask.glsl b/shaders/circle_mask.glsl index 9f82591..0266d2c 100644 --- a/shaders/circle_mask.glsl +++ b/shaders/circle_mask.glsl @@ -1,9 +1,19 @@ uniform sampler2D texture; +uniform vec2 resolution; + +vec4 circle(vec2 uv, vec2 pos, float rad, vec4 color) { + float d = length(pos - uv) - rad; + float t = clamp(d, 0.0, 1.0); + return vec4(color.rgb, color.a * (1.0 - t)); +} void main() { - vec4 pixel = texture2D(texture, gl_TexCoord[0].xy); - vec2 pixelOffset = gl_TexCoord[0].xy - vec2(0.5, 0.5); - float dist = sqrt(dot(pixelOffset, pixelOffset)); - dist = smoothstep(0.47, 0.5, dist); - gl_FragColor = gl_Color * pixel * vec4(1.0, 1.0, 1.0, 1.0 - dist); + vec2 uv = gl_TexCoord[0].xy * resolution; + vec2 center = resolution * 0.5; + float radius = 0.49 * resolution.y; + + vec4 texture_color = texture2D(texture, gl_TexCoord[0].xy); + vec4 layer1 = vec4(0.0, 0.0, 0.0, 0.0); + vec4 layer2 = circle(uv, center, radius, texture_color); + gl_FragColor = mix(layer1, layer2, layer2.a); } diff --git a/shaders/rounded_rectangle.glsl b/shaders/rounded_rectangle.glsl new file mode 100644 index 0000000..7da0826 --- /dev/null +++ b/shaders/rounded_rectangle.glsl @@ -0,0 +1,15 @@ +uniform float radius; +uniform vec2 resolution; + +float rounded_rect(vec2 coord, vec2 size, float r) { + return length(max(abs(coord) - size, 0.0)) - r; +} + +void main() { + vec2 uv = gl_TexCoord[0].xy * resolution; + vec2 center = resolution * 0.5; + vec2 size = resolution * 0.5; + vec4 background_color = vec4(0.0, 0.0, 0.0, 0.0); + float a = clamp(rounded_rect(uv - center, size - radius, radius), 0.0, 1.0); + gl_FragColor = mix(gl_Color, background_color, a); +}
\ No newline at end of file diff --git a/src/Body.cpp b/src/Body.cpp index 534f2b5..a84256e 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -113,7 +113,7 @@ namespace QuickMedia { reactions.push_back(std::move(reaction)); } - Body::Body(Program *program, sf::Texture &loading_icon_texture) : + Body::Body(Program *program, sf::Texture &loading_icon_texture, sf::Shader *rounded_rectangle_shader) : progress_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14 * get_ui_scale())), replies_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14 * get_ui_scale())), embedded_item_load_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), embedded_item_font_size), @@ -126,19 +126,20 @@ namespace QuickMedia { selected_item(0), prev_selected_item(0), page_scroll(0.0f), - item_background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10), loading_icon(loading_icon_texture), num_visible_items(0), first_item_fully_visible(true), last_item_fully_visible(true), first_fully_visible_item(-1), - last_fully_visible_item(-1) + last_fully_visible_item(-1), + item_background(sf::Vector2f(1.0f, 1.0f), 10.0f, sf::Color(55, 60, 68), rounded_rectangle_shader), + reaction_background(sf::Vector2f(1.0f, 1.0f), 10.0f, sf::Color(33, 37, 44), rounded_rectangle_shader) { + assert(rounded_rectangle_shader); progress_text.setFillColor(sf::Color::White); replies_text.setFillColor(sf::Color(129, 162, 190)); thumbnail_max_size.x = 250; thumbnail_max_size.y = 141; - item_background.setFillColor(sf::Color(55, 60, 68)); 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); } @@ -982,9 +983,9 @@ namespace QuickMedia { //window.draw(item_separator); if(item_index == selected_item) { - item_background.setPosition(item_pos); - item_background.setSize(sf::Vector2f(size.x, item_height)); - window.draw(item_background); + item_background.set_position(item_pos); + item_background.set_size(sf::Vector2f(size.x, item_height)); + item_background.draw(window); } float text_offset_x = padding_x; @@ -1011,10 +1012,12 @@ namespace QuickMedia { image.setColor(sf::Color(255, 255, 255, thumbnail_fade_progress * 255)); image.setScale(image_scale); image.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y)); - if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) + 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 + } else { window.draw(image); + } text_offset_x += 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)); @@ -1113,8 +1116,6 @@ namespace QuickMedia { } if(!item->reactions.empty() && include_embedded_item) { - sf::RoundedRectangleShape reaction_background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10); - reaction_background.setFillColor(sf::Color(33, 37, 44)); float reaction_offset_x = 0.0f; item_pos.y += reaction_padding_y; float reaction_max_height = 0.0f; @@ -1125,9 +1126,9 @@ namespace QuickMedia { reaction.text->updateGeometry(); reaction_max_height = std::max(reaction_max_height, reaction.text->getHeight()); reaction.text->setPosition(std::floor(item_pos.x + text_offset_x + reaction_offset_x + reaction_background_padding_x), std::floor(item_pos.y + padding_y - 4.0f + reaction_background_padding_y)); - reaction_background.setPosition(std::floor(item_pos.x + text_offset_x + reaction_offset_x), std::floor(item_pos.y + padding_y)); - reaction_background.setSize(sf::Vector2f(reaction.text->getWidth() + reaction_background_padding_x * 2.0f, reaction.text->getHeight() + reaction_background_padding_y * 2.0f)); - window.draw(reaction_background); + reaction_background.set_position(sf::Vector2f(std::floor(item_pos.x + text_offset_x + reaction_offset_x), std::floor(item_pos.y + padding_y))); + reaction_background.set_size(sf::Vector2f(reaction.text->getWidth() + reaction_background_padding_x * 2.0f, reaction.text->getHeight() + reaction_background_padding_y * 2.0f)); + reaction_background.draw(window); reaction_offset_x += reaction.text->getWidth() + reaction_background_padding_x * 2.0f + reaction_spacing_x; reaction.text->draw(window); if(text_offset_x + reaction_offset_x + reaction.text->getWidth() + reaction_background_padding_x * 2.0f > size.x && i < (int)item->reactions.size() - 1) { diff --git a/src/Entry.cpp b/src/Entry.cpp index 5a6110c..96a34f3 100644 --- a/src/Entry.cpp +++ b/src/Entry.cpp @@ -11,29 +11,28 @@ const float padding_vertical = std::floor(3.0f * QuickMedia::get_ui_scale()); const float background_margin_vertical = std::floor(0.0f * QuickMedia::get_ui_scale()); namespace QuickMedia { - Entry::Entry(const std::string &placeholder_text) : + Entry::Entry(const std::string &placeholder_text, sf::Shader *rounded_rectangle_shader) : on_submit_callback(nullptr), draw_background(true), text("", false, std::floor(16 * get_ui_scale()), 0.0f), width(0.0f), - background(sf::Vector2f(1.0f, 1.0f), 7.0f, 10), + background(sf::Vector2f(1.0f, 1.0f), 7.0f, sf::Color(55, 60, 68), rounded_rectangle_shader), placeholder(placeholder_text, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16 * get_ui_scale())), mouse_left_inside(false) { text.setEditable(true); - background.setFillColor(sf::Color(55, 60, 68)); placeholder.setFillColor(sf::Color(255, 255, 255, 100)); } 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.getPosition(), background.getSize()); + sf::FloatRect box(background.get_position(), background.get_size()); if(box.contains(event.mouseButton.x, event.mouseButton.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.getPosition(), background.getSize()); + sf::FloatRect box(background.get_position(), background.get_size()); if(mouse_left_inside && box.contains(event.mouseButton.x, event.mouseButton.y)) show_virtual_keyboard(); mouse_left_inside = false; @@ -58,9 +57,9 @@ 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.setSize(sf::Vector2f(width, get_height())); + background.set_size(sf::Vector2f(width, get_height())); if(draw_background) - window.draw(background); + background.draw(window); if(text.getString().isEmpty() && !text.isEditable()) { window.draw(placeholder); @@ -93,7 +92,7 @@ namespace QuickMedia { } void Entry::set_position(const sf::Vector2f &pos) { - background.setPosition(pos); + background.set_position(pos); text.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical - std::floor(3.0f * get_ui_scale()))); placeholder.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical + std::floor(3.0f * get_ui_scale()))); } diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 79f1f74..4de65d2 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -645,12 +645,17 @@ namespace QuickMedia { set_resource_loader_root_path(resources_root.c_str()); 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()); + fprintf(stderr, "Failed to load %s/shaders/circle_mask.glsl\n", resources_root.c_str()); + abort(); + } + + if(!rounded_rectangle_shader.loadFromFile(resources_root + "shaders/rounded_rectangle.glsl", sf::Shader::Type::Fragment)) { + fprintf(stderr, "Failed to load %s/shaders/rounded_rectangle.glsl\n", resources_root.c_str()); abort(); } if(!loading_icon.loadFromFile(resources_root + "images/loading_icon.png")) { - fprintf(stderr, "Failed to load %s/images/loading_icon.png", resources_root.c_str()); + fprintf(stderr, "Failed to load %s/images/loading_icon.png\n", resources_root.c_str()); abort(); } loading_icon.setSmooth(true); @@ -1177,13 +1182,13 @@ namespace QuickMedia { } std::unique_ptr<Body> Program::create_body() { - auto body = std::make_unique<Body>(this, loading_icon); + auto body = std::make_unique<Body>(this, loading_icon, &rounded_rectangle_shader); body->thumbnail_mask_shader = &circle_mask_shader; return body; } std::unique_ptr<SearchBar> Program::create_search_bar(const std::string &placeholder, int search_delay) { - auto search_bar = std::make_unique<SearchBar>(&plugin_logo, placeholder); + auto search_bar = std::make_unique<SearchBar>(&plugin_logo, &rounded_rectangle_shader, placeholder); search_bar->text_autosearch_delay = search_delay; return search_bar; } @@ -1290,7 +1295,7 @@ namespace QuickMedia { tab.page->on_navigate_to_page(tab.body.get()); } - Tabs ui_tabs; + Tabs ui_tabs(&rounded_rectangle_shader); for(auto &tab : tabs) { ui_tabs.add_tab(tab.page->get_title()); } @@ -2936,7 +2941,7 @@ namespace QuickMedia { }); }; - Entry comment_input("Press i to begin writing a comment..."); + Entry comment_input("Press i to begin writing a comment...", &rounded_rectangle_shader); comment_input.draw_background = false; comment_input.set_editable(false); @@ -3328,9 +3333,9 @@ namespace QuickMedia { void Program::chat_login_page() { assert(strcmp(plugin_name, "matrix") == 0); - SearchBar login_input(nullptr, "Username"); - SearchBar password_input(nullptr, "Password", true); - SearchBar homeserver_input(nullptr, "Homeserver"); + SearchBar login_input(nullptr, &rounded_rectangle_shader, "Username"); + SearchBar password_input(nullptr, &rounded_rectangle_shader, "Password", true); + SearchBar homeserver_input(nullptr, &rounded_rectangle_shader, "Homeserver"); sf::Text status_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(18 * get_ui_scale())); @@ -3566,31 +3571,28 @@ namespace QuickMedia { std::vector<ChatTab> tabs; ChatTab pinned_tab; - pinned_tab.body = std::make_unique<Body>(this, loading_icon); + pinned_tab.body = create_body(); pinned_tab.body->thumbnail_max_size = CHAT_MESSAGE_THUMBNAIL_MAX_SIZE; - pinned_tab.body->thumbnail_mask_shader = &circle_mask_shader; pinned_tab.body->attach_side = AttachSide::BOTTOM; pinned_tab.body->line_separator_color = sf::Color::Transparent; tabs.push_back(std::move(pinned_tab)); ChatTab messages_tab; - messages_tab.body = std::make_unique<Body>(this, loading_icon); + messages_tab.body = create_body(); messages_tab.body->thumbnail_max_size = CHAT_MESSAGE_THUMBNAIL_MAX_SIZE; - messages_tab.body->thumbnail_mask_shader = &circle_mask_shader; messages_tab.body->attach_side = AttachSide::BOTTOM; messages_tab.body->line_separator_color = sf::Color::Transparent; tabs.push_back(std::move(messages_tab)); // ChatTab users_tab; - // users_tab.body = std::make_unique<Body>(this, loading_icon); + // users_tab.body = create_body(); // users_tab.body->thumbnail_max_size = CHAT_MESSAGE_THUMBNAIL_MAX_SIZE; - // users_tab.body->thumbnail_mask_shader = &circle_mask_shader; // users_tab.body->attach_side = AttachSide::TOP; // //users_tab.body->line_separator_color = sf::Color::Transparent; // users_tab.text = sf::Text("Users", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size); // tabs.push_back(std::move(users_tab)); - Tabs ui_tabs(back_color); + Tabs ui_tabs(&rounded_rectangle_shader, back_color); const int PINNED_TAB_INDEX = ui_tabs.add_tab("Pinned messages (0)"); const int MESSAGES_TAB_INDEX = ui_tabs.add_tab("Messages"); ui_tabs.set_selected(MESSAGES_TAB_INDEX); @@ -3855,7 +3857,7 @@ namespace QuickMedia { ui_tabs.set_text(PINNED_TAB_INDEX, "Pinned messages (" + std::to_string(tabs[PINNED_TAB_INDEX].body->items.size()) + ")"); }; - Body url_selection_body(this, loading_icon); + Body url_selection_body(this, loading_icon, &rounded_rectangle_shader); std::unordered_set<std::string> fetched_messages_set; auto filter_existing_messages = [&fetched_messages_set](Messages &messages) { @@ -3895,7 +3897,7 @@ namespace QuickMedia { read_marker_timeout_ms = 0; redraw = true; - Entry chat_input("Press i to begin writing a message..."); + Entry chat_input("Press i to begin writing a message...", &rounded_rectangle_shader); chat_input.draw_background = false; chat_input.set_editable(false); @@ -5096,6 +5098,7 @@ 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); + circle_mask_shader.setUniform("resolution", sf::Vector2f(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; } diff --git a/src/RoundedRectangle.cpp b/src/RoundedRectangle.cpp new file mode 100644 index 0000000..6b956e8 --- /dev/null +++ b/src/RoundedRectangle.cpp @@ -0,0 +1,46 @@ +#include "../include/RoundedRectangle.hpp" +#include <SFML/Graphics/Shader.hpp> +#include <SFML/Graphics/RenderWindow.hpp> +#include <assert.h> + +namespace QuickMedia { + 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) { + assert(rounded_rectangle_shader); + vertices[0].color = color; + vertices[1].color = color; + vertices[2].color = color; + vertices[3].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); + } + + void RoundedRectangle::set_position(sf::Vector2f pos) { + this->pos = pos; + vertices[0].position = pos; + vertices[1].position = pos + sf::Vector2f(size.x, 0.0f); + vertices[2].position = pos + sf::Vector2f(size.x, size.y); + vertices[3].position = pos + sf::Vector2f(0.0f, size.y); + } + + void RoundedRectangle::set_size(sf::Vector2f size) { + this->size = size; + set_position(pos); + } + + sf::Vector2f RoundedRectangle::get_position() const { + return pos; + } + + sf::Vector2f RoundedRectangle::get_size() const { + return size; + } + + void RoundedRectangle::draw(sf::RenderWindow &window) { + rounded_rectangle_shader->setUniform("resolution", size); + rounded_rectangle_shader->setUniform("radius", radius); + window.draw(vertices, 4, sf::Quads, rounded_rectangle_shader); + } +}
\ No newline at end of file diff --git a/src/SearchBar.cpp b/src/SearchBar.cpp index fa119a6..6aa6eec 100644 --- a/src/SearchBar.cpp +++ b/src/SearchBar.cpp @@ -19,7 +19,7 @@ static const float padding_bottom = std::floor(15.0f * QuickMedia::get_ui_scale( static const float background_margin_vertical = std::floor(4.0f * QuickMedia::get_ui_scale()); namespace QuickMedia { - SearchBar::SearchBar(sf::Texture *plugin_logo, const std::string &placeholder, bool input_masked) : + SearchBar::SearchBar(sf::Texture *plugin_logo, sf::Shader *rounded_rectangle_shader, const std::string &placeholder, bool input_masked) : onTextUpdateCallback(nullptr), onTextSubmitCallback(nullptr), onTextBeginTypingCallback(nullptr), @@ -29,7 +29,7 @@ namespace QuickMedia { caret_visible(true), text(placeholder, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16 * get_ui_scale())), autocomplete_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16 * get_ui_scale())), - background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10), + background(sf::Vector2f(1.0f, 1.0f), 10.0f, front_color, rounded_rectangle_shader), placeholder_str(placeholder), show_placeholder(true), updated_search(false), @@ -44,7 +44,6 @@ namespace QuickMedia { { text.setFillColor(text_placeholder_color); autocomplete_text.setFillColor(text_placeholder_color); - background.setFillColor(front_color); //background.setCornersRadius(5); background_shadow.setFillColor(sf::Color(23, 25, 27)); //background_shadow.setPosition(background.getPosition() + sf::Vector2f(5.0f, 5.0f)); @@ -65,7 +64,7 @@ namespace QuickMedia { //if(draw_shadow) // window.draw(background_shadow); window.draw(shade); - window.draw(background); + background.draw(window); // TODO: Render starting from the character after text length window.draw(autocomplete_text); if(input_masked && !show_placeholder) { @@ -112,13 +111,13 @@ namespace QuickMedia { onTextEntered(8); if(is_touch_enabled() && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) { - sf::FloatRect box(background.getPosition(), background.getSize()); + sf::FloatRect box(background.get_position(), background.get_size()); if(box.contains(event.mouseButton.x, event.mouseButton.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.getPosition(), background.getSize()); + sf::FloatRect box(background.get_position(), background.get_size()); if(mouse_left_inside && box.contains(event.mouseButton.x, event.mouseButton.y)) show_virtual_keyboard(); mouse_left_inside = false; @@ -175,12 +174,12 @@ namespace QuickMedia { const float width = std::floor(window_size.x - offset_x - 10.0f); - background.setSize(sf::Vector2f(width, rect_height)); + background.set_size(sf::Vector2f(width, rect_height)); shade.setSize(sf::Vector2f(window_size.x, padding_top + rect_height + padding_bottom)); caret.setSize(sf::Vector2f(std::floor(2.0f * get_ui_scale()), text.getCharacterSize() + std::floor(2.0f * get_ui_scale()))); background_shadow.setSize(sf::Vector2f(window_size.x, 5.0f)); - background.setPosition(offset_x, padding_top + vertical_pos); + background.set_position(sf::Vector2f(offset_x, padding_top + vertical_pos)); shade.setPosition(0.0f, vertical_pos); background_shadow.setPosition(0.0f, std::floor(shade.getSize().y + vertical_pos)); sf::Vector2f font_position(std::floor(offset_x + background_margin_horizontal), std::floor(padding_top + background_margin_vertical + vertical_pos)); @@ -308,10 +307,6 @@ namespace QuickMedia { } } - void SearchBar::set_background_color(sf::Color color) { - background.setFillColor(color); - } - void SearchBar::clear_autocomplete_if_text_not_substring() { const sf::String &text_str = text.getString(); const sf::String &autocomplete_str = autocomplete_text.getString(); diff --git a/src/Tabs.cpp b/src/Tabs.cpp index eb435fc..4437472 100644 --- a/src/Tabs.cpp +++ b/src/Tabs.cpp @@ -24,8 +24,7 @@ namespace QuickMedia { return tab_height + std::floor(10.0f * get_ui_scale()); } - Tabs::Tabs(sf::Color shade_color) : background(sf::Vector2f(1.0f, 1.0f), 10.0f, 10), shade_color(shade_color) { - background.setFillColor(tab_selected_color); + Tabs::Tabs(sf::Shader *rounded_rectangle_shader, sf::Color shade_color) : background(sf::Vector2f(1.0f, 1.0f), 10.0f, tab_selected_color, rounded_rectangle_shader), shade_color(shade_color) { shade.setFillColor(shade_color); } @@ -70,7 +69,7 @@ namespace QuickMedia { 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_ui_scale())*0.5f); tab_background_width = std::floor(width_per_tab - tab_margin_x*2.0f); - background.setSize(sf::Vector2f(tab_background_width, tab_height)); + background.set_size(sf::Vector2f(tab_background_width, tab_height)); shade.setSize(sf::Vector2f(width, get_shade_height())); shade.setPosition(std::floor(pos.x), std::floor(pos.y)); @@ -106,8 +105,8 @@ namespace QuickMedia { } if((int)index == selected_tab) { - background.setPosition(background_pos_x, std::floor(pos.y)); - window.draw(background); + background.set_position(sf::Vector2f(background_pos_x, std::floor(pos.y))); + background.draw(window); } sf::Text &tab_text = tab_texts[index]; @@ -121,7 +120,7 @@ namespace QuickMedia { } float lw = std::floor(25.0f * get_ui_scale()); - float lh = background.getSize().y; + float lh = background.get_size().y; float line_offset_y = std::floor(lw * 0.35f); @@ -144,11 +143,11 @@ namespace QuickMedia { 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.getSize().y * 0.5f - lh * 0.5f + line_offset_y)); + 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.getSize().y * 0.5f - lh * 0.5f + line_offset_y + std::floor(7.0f * get_ui_scale()))); + 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_ui_scale()))); window.draw(line); } @@ -171,11 +170,11 @@ namespace QuickMedia { 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.getSize().y * 0.5f - lh * 0.5f + line_offset_y)); + 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.getSize().y * 0.5f - lh * 0.5f + line_offset_y + std::floor(7.0f * get_ui_scale()))); + 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_ui_scale()))); window.draw(line); } } |