From 48fe7b05b92399e5c50780ef61002ae3f37a94ca Mon Sep 17 00:00:00 2001 From: f0e <7321764+f0e@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:32:31 +1000 Subject: [PATCH] refactor: split out elements into separate files, remove unused has_content_changed function --- src/gui/ui/elements/bar.cpp | 51 ++++++ src/gui/ui/elements/button.cpp | 57 +++++++ src/gui/ui/elements/image.cpp | 101 ++++++++++++ src/gui/ui/elements/text.cpp | 41 +++++ src/gui/ui/ui.cpp | 278 --------------------------------- src/gui/ui/utils.cpp | 4 + src/gui/ui/utils.h | 2 + 7 files changed, 256 insertions(+), 278 deletions(-) create mode 100644 src/gui/ui/elements/bar.cpp create mode 100644 src/gui/ui/elements/button.cpp create mode 100644 src/gui/ui/elements/image.cpp create mode 100644 src/gui/ui/elements/text.cpp diff --git a/src/gui/ui/elements/bar.cpp b/src/gui/ui/elements/bar.cpp new file mode 100644 index 0000000..d853118 --- /dev/null +++ b/src/gui/ui/elements/bar.cpp @@ -0,0 +1,51 @@ +#include "../ui.h" +#include "../render.h" +#include "../utils.h" + +void ui::render_bar(os::Surface* surface, const Element* element, float anim) { + const int text_gap = 7; + + auto& bar_data = std::get(element->data); + + gfx::Color adjusted_background_color = utils::adjust_color(bar_data.background_color, anim); + gfx::Color adjusted_fill_color = utils::adjust_color(bar_data.fill_color, anim); + + gfx::Size text_size(0, 0); + + if (bar_data.bar_text && bar_data.text_color && bar_data.font) { + gfx::Color adjusted_text_color = utils::adjust_color(*bar_data.text_color, anim); + + gfx::Point text_pos = element->rect.origin(); + + text_size = render::get_text_size(*bar_data.bar_text, **bar_data.font); + + text_pos.x = element->rect.x2(); + text_pos.y += (*bar_data.font)->getSize() / 2; + + render::text(surface, text_pos, adjusted_text_color, *bar_data.bar_text, **bar_data.font, os::TextAlign::Right); + } + + gfx::Rect bar_rect = element->rect; + bar_rect.w -= text_size.w + text_gap; + + render::rounded_rect_filled(surface, bar_rect, adjusted_background_color, 1000.f); + + if (bar_data.percent_fill > 0) { + gfx::Rect fill_rect = bar_rect; + fill_rect.w = static_cast(bar_rect.w * bar_data.percent_fill); + render::rounded_rect_filled(surface, fill_rect, adjusted_fill_color, 1000.f); + } +} + +std::shared_ptr ui::add_bar(const std::string& id, Container& container, float percent_fill, gfx::Color background_color, gfx::Color fill_color, int bar_width, std::optional bar_text, std::optional text_color, std::optional font) { + auto element = std::make_shared(Element{ + ElementType::BAR, + gfx::Rect(container.current_position, gfx::Size(bar_width, 6)), + BarElementData{ percent_fill, background_color, fill_color, bar_text, text_color, font }, + render_bar, + }); + + add_element(container, id, element, container.line_height); + + return element; +} diff --git a/src/gui/ui/elements/button.cpp b/src/gui/ui/elements/button.cpp new file mode 100644 index 0000000..38a7a21 --- /dev/null +++ b/src/gui/ui/elements/button.cpp @@ -0,0 +1,57 @@ +#include "../ui.h" +#include "../render.h" +#include "../utils.h" +#include "../keys.h" +#include "../../gui.h" + +void ui::render_button(os::Surface* surface, const Element* element, float anim) { + const float button_rounding = 7.8f; + + auto& button_data = std::get(element->data); + + bool hovered = element->rect.contains(keys::mouse_pos); + if (hovered) { + gui::set_cursor(os::NativeCursor::Link); + + if (button_data.on_press) { + if (keys::is_mouse_down()) { + (*button_data.on_press)(); + keys::on_mouse_press_handled(os::Event::MouseButton::LeftButton); + } + } + } + + gfx::Color adjusted_color = utils::adjust_color(gfx::rgba(255, 255, 255, hovered ? 75 : 20), anim); // todo: lerp hover shade + gfx::Color adjusted_text_color = utils::adjust_color(gfx::rgba(255, 255, 255, 255), anim); + + gfx::Point text_pos = element->rect.center(); + + text_pos.y += button_data.font.getSize() / 2 - 1; + gfx::Rect cur_rect = element->rect; + + // border + cur_rect.shrink(1); + render::rounded_rect_stroke(surface, cur_rect, utils::adjust_color(gfx::rgba(100, 100, 100, 255), anim), button_rounding); + + // fill + render::rounded_rect_filled(surface, cur_rect, adjusted_color, button_rounding); + + render::text(surface, text_pos, adjusted_text_color, button_data.text, button_data.font, os::TextAlign::Center); +} + +std::shared_ptr ui::add_button(const std::string& id, Container& container, const std::string& text, const SkFont& font, std::optional> on_press) { + const gfx::Size button_padding(40, 20); + + gfx::Size text_size = render::get_text_size(text, font); + + auto element = std::make_shared(Element{ + ElementType::BUTTON, + gfx::Rect(container.current_position, text_size + button_padding), + ButtonElementData{ text, font, on_press }, + render_button, + }); + + add_element(container, id, element, container.line_height); + + return element; +} diff --git a/src/gui/ui/elements/image.cpp b/src/gui/ui/elements/image.cpp new file mode 100644 index 0000000..32ad85d --- /dev/null +++ b/src/gui/ui/elements/image.cpp @@ -0,0 +1,101 @@ +#include "../ui.h" + +void ui::render_image(os::Surface* surface, const Element* element, float anim) { + auto& image_data = std::get(element->data); + + int alpha = anim * 255; + int stroke_alpha = anim * 125; + + gfx::Rect image_rect = element->rect; + image_rect.shrink(3); + + os::Paint paint; + paint.color(gfx::rgba(255, 255, 255, alpha)); + surface->drawSurface(image_data.image_surface.get(), image_data.image_surface->bounds(), image_rect, os::Sampling(), &paint); + + os::Paint stroke_paint; + stroke_paint.style(os::Paint::Style::Stroke); + stroke_paint.strokeWidth(1); + + image_rect.enlarge(1); + stroke_paint.color(gfx::rgba(155, 155, 155, stroke_alpha)); + surface->drawRect(image_rect, stroke_paint); + + image_rect.enlarge(1); + stroke_paint.color(gfx::rgba(80, 80, 80, stroke_alpha)); + surface->drawRect(image_rect, stroke_paint); + + image_rect.enlarge(1); + stroke_paint.color(gfx::rgba(155, 155, 155, stroke_alpha)); + surface->drawRect(image_rect, stroke_paint); +} + +std::optional> ui::add_image(const std::string& id, Container& container, std::string image_path, gfx::Size max_size, std::string image_id) { + os::SurfaceRef image_surface; + os::SurfaceRef last_image_surface; + + // get existing image + if (container.elements.contains(id)) { + std::shared_ptr cached_element = container.elements[id].element; + auto& image_data = std::get(cached_element->data); + if (image_data.image_id == image_id) { // edge cases this might not work, it's using current_frame, maybe image gets written after ffmpeg reports progress? idk. good enough for now + image_surface = image_data.image_surface; + } + else { + last_image_surface = image_data.image_surface; + } + } + + // load image if new + if (!image_surface) { + image_surface = os::instance()->loadRgbaSurface(image_path.c_str()); + + if (!image_surface) { + printf("%s failed to load image (id: %s)\n", id.c_str(), image_id.c_str()); + if (last_image_surface) { + // use last image as fallback todo: this is a bit hacky make it better + image_surface = last_image_surface; + } + else { + return {}; + } + } + + printf("%s loaded image (id: %s)\n", id.c_str(), image_id.c_str()); + } + + gfx::Rect image_rect(container.current_position, max_size); + + float aspect_ratio = image_surface->width() / static_cast(image_surface->height()); + + float target_width = image_rect.h * aspect_ratio; + float target_height = image_rect.w / aspect_ratio; + + if (target_width <= image_rect.w) { + image_rect.w = static_cast(target_width); + } + else { + image_rect.h = static_cast(target_height); + } + + if (image_rect.h > max_size.h) { + image_rect.h = max_size.h; + image_rect.w = static_cast(max_size.h * aspect_ratio); + } + + if (image_rect.w > max_size.w) { + image_rect.w = max_size.w; + image_rect.h = static_cast(max_size.w / aspect_ratio); + } + + auto element = std::make_shared(Element{ + ElementType::IMAGE, + image_rect, + ImageElementData{ image_path, image_surface, image_id }, + render_image, + }); + + add_element(container, id, element, container.line_height); + + return element; +} diff --git a/src/gui/ui/elements/text.cpp b/src/gui/ui/elements/text.cpp new file mode 100644 index 0000000..c6f2619 --- /dev/null +++ b/src/gui/ui/elements/text.cpp @@ -0,0 +1,41 @@ +#include "../ui.h" +#include "../render.h" +#include "../utils.h" + +void ui::render_text(os::Surface* surface, const Element* element, float anim) { + auto& text_data = std::get(element->data); + + gfx::Color adjusted_color = utils::adjust_color(text_data.color, anim); + + gfx::Point text_pos = element->rect.origin(); + text_pos.y += text_data.font.getSize() - 1; + + render::text(surface, text_pos, adjusted_color, text_data.text, text_data.font, text_data.align); +} + +std::shared_ptr ui::add_text(const std::string& id, Container& container, const std::string& text, gfx::Color color, const SkFont& font, os::TextAlign align, int margin_bottom) { + auto element = std::make_shared(Element{ + ElementType::TEXT, + gfx::Rect(container.current_position, gfx::Size(0, font.getSize())), + TextElementData{ text, color, font, align }, + render_text, + }); + + add_element(container, id, element, margin_bottom); + + return element; +} + +std::shared_ptr ui::add_text_fixed(const std::string& id, Container& container, gfx::Point position, const std::string& text, gfx::Color color, const SkFont& font, os::TextAlign align, int margin_bottom) { + auto element = std::make_shared(Element{ + ElementType::TEXT, + gfx::Rect(position, gfx::Size(0, font.getSize())), + TextElementData{ text, color, font, align }, + render_text, + true, + }); + + add_element_fixed(container, id, element); + + return element; +} diff --git a/src/gui/ui/ui.cpp b/src/gui/ui/ui.cpp index ffa3fcb..9bd0b36 100644 --- a/src/gui/ui/ui.cpp +++ b/src/gui/ui/ui.cpp @@ -1,157 +1,6 @@ #include "ui.h" -#include "gui/gui.h" -#include "os/native_cursor.h" #include "render.h" -#include "keys.h" #include "os/draw_text.h" -#include "os/sampling.h" - -gfx::Color adjust_color(const gfx::Color& color, float anim) { - return gfx::rgba(gfx::getr(color), gfx::getg(color), gfx::getb(color), round(gfx::geta(color) * anim)); // seta is broken or smth i swear -} - -bool has_content_changed(const ui::Element* existing, const ui::Element* new_element) { - if (existing->type != new_element->type) - return true; - - switch (existing->type) { - case ui::ElementType::BAR: { - const auto& existing_data = std::get(existing->data); - const auto& new_data = std::get(new_element->data); - return existing_data.percent_fill != new_data.percent_fill || - existing_data.background_color != new_data.background_color || - existing_data.fill_color != new_data.fill_color || - existing_data.bar_text != new_data.bar_text || - existing_data.text_color != new_data.text_color; - } - case ui::ElementType::TEXT: { - const auto& existing_data = std::get(existing->data); - const auto& new_data = std::get(new_element->data); - return existing_data.text != new_data.text || - existing_data.color != new_data.color || - existing_data.align != new_data.align; - } - case ui::ElementType::IMAGE: { - const auto& existing_data = std::get(existing->data); - const auto& new_data = std::get(new_element->data); - return existing_data.image_id != new_data.image_id || - existing_data.image_path != new_data.image_path; - } - default: - return false; - } -} - -void ui::render_bar(os::Surface* surface, const Element* element, float anim) { - const int text_gap = 7; - - auto& bar_data = std::get(element->data); - - gfx::Color adjusted_background_color = adjust_color(bar_data.background_color, anim); - gfx::Color adjusted_fill_color = adjust_color(bar_data.fill_color, anim); - - gfx::Size text_size(0, 0); - - if (bar_data.bar_text && bar_data.text_color && bar_data.font) { - gfx::Color adjusted_text_color = adjust_color(*bar_data.text_color, anim); - - gfx::Point text_pos = element->rect.origin(); - - text_size = render::get_text_size(*bar_data.bar_text, **bar_data.font); - - text_pos.x = element->rect.x2(); - text_pos.y += (*bar_data.font)->getSize() / 2; - - render::text(surface, text_pos, adjusted_text_color, *bar_data.bar_text, **bar_data.font, os::TextAlign::Right); - } - - gfx::Rect bar_rect = element->rect; - bar_rect.w -= text_size.w + text_gap; - - render::rounded_rect_filled(surface, bar_rect, adjusted_background_color, 1000.f); - - if (bar_data.percent_fill > 0) { - gfx::Rect fill_rect = bar_rect; - fill_rect.w = static_cast(bar_rect.w * bar_data.percent_fill); - render::rounded_rect_filled(surface, fill_rect, adjusted_fill_color, 1000.f); - } -} - -void ui::render_text(os::Surface* surface, const Element* element, float anim) { - auto& text_data = std::get(element->data); - - gfx::Color adjusted_color = adjust_color(text_data.color, anim); - - gfx::Point text_pos = element->rect.origin(); - text_pos.y += text_data.font.getSize() - 1; - - render::text(surface, text_pos, adjusted_color, text_data.text, text_data.font, text_data.align); -} - -void ui::render_image(os::Surface* surface, const Element* element, float anim) { - auto& image_data = std::get(element->data); - - int alpha = anim * 255; - int stroke_alpha = anim * 125; - - gfx::Rect image_rect = element->rect; - image_rect.shrink(3); - - os::Paint paint; - paint.color(gfx::rgba(255, 255, 255, alpha)); - surface->drawSurface(image_data.image_surface.get(), image_data.image_surface->bounds(), image_rect, os::Sampling(), &paint); - - os::Paint stroke_paint; - stroke_paint.style(os::Paint::Style::Stroke); - stroke_paint.strokeWidth(1); - - image_rect.enlarge(1); - stroke_paint.color(gfx::rgba(155, 155, 155, stroke_alpha)); - surface->drawRect(image_rect, stroke_paint); - - image_rect.enlarge(1); - stroke_paint.color(gfx::rgba(80, 80, 80, stroke_alpha)); - surface->drawRect(image_rect, stroke_paint); - - image_rect.enlarge(1); - stroke_paint.color(gfx::rgba(155, 155, 155, stroke_alpha)); - surface->drawRect(image_rect, stroke_paint); -} - -void ui::render_button(os::Surface* surface, const Element* element, float anim) { - const float button_rounding = 7.8f; - - auto& button_data = std::get(element->data); - - bool hovered = element->rect.contains(keys::mouse_pos); - if (hovered) { - gui::set_cursor(os::NativeCursor::Link); - - if (button_data.on_press) { - if (keys::is_mouse_down()) { - (*button_data.on_press)(); - keys::on_mouse_press_handled(os::Event::MouseButton::LeftButton); - } - } - } - - gfx::Color adjusted_color = adjust_color(gfx::rgba(255, 255, 255, hovered ? 75 : 20), anim); // todo: lerp hover shade - gfx::Color adjusted_text_color = adjust_color(gfx::rgba(255, 255, 255, 255), anim); - - gfx::Point text_pos = element->rect.center(); - - text_pos.y += button_data.font.getSize() / 2 - 1; - gfx::Rect cur_rect = element->rect; - - // border - cur_rect.shrink(1); - render::rounded_rect_stroke(surface, cur_rect, adjust_color(gfx::rgba(100, 100, 100, 255), anim), button_rounding); - - // fill - render::rounded_rect_filled(surface, cur_rect, adjusted_color, button_rounding); - - render::text(surface, text_pos, adjusted_text_color, button_data.text, button_data.font, os::TextAlign::Center); -} void ui::init_container(Container& container, gfx::Rect rect, const SkFont& font, std::optional background_color) { container.line_height = font.getSize(); @@ -188,133 +37,6 @@ void ui::add_element_fixed(Container& container, const std::string& id, std::sha container.current_element_ids.push_back(id); } -std::shared_ptr ui::add_bar(const std::string& id, Container& container, float percent_fill, gfx::Color background_color, gfx::Color fill_color, int bar_width, std::optional bar_text, std::optional text_color, std::optional font) { - auto element = std::make_shared(Element{ - ElementType::BAR, - gfx::Rect(container.current_position, gfx::Size(bar_width, 6)), - BarElementData{ percent_fill, background_color, fill_color, bar_text, text_color, font }, - render_bar, - }); - - add_element(container, id, element, container.line_height); - - return element; -} - -std::shared_ptr ui::add_text(const std::string& id, Container& container, const std::string& text, gfx::Color color, const SkFont& font, os::TextAlign align, int margin_bottom) { - auto element = std::make_shared(Element{ - ElementType::TEXT, - gfx::Rect(container.current_position, gfx::Size(0, font.getSize())), - TextElementData{ text, color, font, align }, - render_text, - }); - - add_element(container, id, element, margin_bottom); - - return element; -} - -std::shared_ptr ui::add_text_fixed(const std::string& id, Container& container, gfx::Point position, const std::string& text, gfx::Color color, const SkFont& font, os::TextAlign align, int margin_bottom) { - auto element = std::make_shared(Element{ - ElementType::TEXT, - gfx::Rect(position, gfx::Size(0, font.getSize())), - TextElementData{ text, color, font, align }, - render_text, - true, - }); - - add_element_fixed(container, id, element); - - return element; -} - -std::optional> ui::add_image(const std::string& id, Container& container, std::string image_path, gfx::Size max_size, std::string image_id) { - os::SurfaceRef image_surface; - os::SurfaceRef last_image_surface; - - // get existing image - if (container.elements.contains(id)) { - std::shared_ptr cached_element = container.elements[id].element; - auto& image_data = std::get(cached_element->data); - if (image_data.image_id == image_id) { // edge cases this might not work, it's using current_frame, maybe image gets written after ffmpeg reports progress? idk. good enough for now - image_surface = image_data.image_surface; - } - else { - last_image_surface = image_data.image_surface; - } - } - - // load image if new - if (!image_surface) { - image_surface = os::instance()->loadRgbaSurface(image_path.c_str()); - - if (!image_surface) { - printf("%s failed to load image (id: %s)\n", id.c_str(), image_id.c_str()); - if (last_image_surface) { - // use last image as fallback todo: this is a bit hacky make it better - image_surface = last_image_surface; - } - else { - return {}; - } - } - - printf("%s loaded image (id: %s)\n", id.c_str(), image_id.c_str()); - } - - gfx::Rect image_rect(container.current_position, max_size); - - float aspect_ratio = image_surface->width() / static_cast(image_surface->height()); - - float target_width = image_rect.h * aspect_ratio; - float target_height = image_rect.w / aspect_ratio; - - if (target_width <= image_rect.w) { - image_rect.w = static_cast(target_width); - } - else { - image_rect.h = static_cast(target_height); - } - - if (image_rect.h > max_size.h) { - image_rect.h = max_size.h; - image_rect.w = static_cast(max_size.h * aspect_ratio); - } - - if (image_rect.w > max_size.w) { - image_rect.w = max_size.w; - image_rect.h = static_cast(max_size.w / aspect_ratio); - } - - auto element = std::make_shared(Element{ - ElementType::IMAGE, - image_rect, - ImageElementData{ image_path, image_surface, image_id }, - render_image, - }); - - add_element(container, id, element, container.line_height); - - return element; -} - -std::shared_ptr ui::add_button(const std::string& id, Container& container, const std::string& text, const SkFont& font, std::optional> on_press) { - const gfx::Size button_padding(40, 20); - - gfx::Size text_size = render::get_text_size(text, font); - - auto element = std::make_shared(Element{ - ElementType::BUTTON, - gfx::Rect(container.current_position, text_size + button_padding), - ButtonElementData{ text, font, on_press }, - render_button, - }); - - add_element(container, id, element, container.line_height); - - return element; -} - void ui::center_elements_in_container(Container& container, bool horizontal, bool vertical) { int total_height = container.current_position.y - container.rect.y; diff --git a/src/gui/ui/utils.cpp b/src/gui/ui/utils.cpp index dd394f8..dbf9115 100644 --- a/src/gui/ui/utils.cpp +++ b/src/gui/ui/utils.cpp @@ -11,6 +11,10 @@ # include #endif +gfx::Color utils::adjust_color(const gfx::Color& color, float anim) { + return gfx::rgba(gfx::getr(color), gfx::getg(color), gfx::getb(color), round(gfx::geta(color) * anim)); // seta is broken or smth i swear +} + SkFont utils::create_font_from_data(const unsigned char* font_data, size_t data_size, float font_height) { sk_sp skData = SkData::MakeWithCopy(font_data, data_size); diff --git a/src/gui/ui/utils.h b/src/gui/ui/utils.h index 36c2148..2fb53ae 100644 --- a/src/gui/ui/utils.h +++ b/src/gui/ui/utils.h @@ -1,6 +1,8 @@ #pragma once namespace utils { + gfx::Color adjust_color(const gfx::Color& color, float anim); + SkFont create_font_from_data(const unsigned char* font_data, size_t data_size, float font_height); #ifdef _WIN32