diff options
author | dec05eba <dec05eba@protonmail.com> | 2024-08-01 18:38:06 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2024-08-01 18:38:06 +0200 |
commit | 6624db873c91087bc1805b9d018c92c455b85190 (patch) | |
tree | 169010942015f1ff209cd56600f4de433c8792ef | |
parent | 5d40409fc6e54af4c4dccdab11f03bce21c5a9a2 (diff) |
Move dropdown button text and icon code to dropdown button class
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | include/GsrInfo.hpp | 66 | ||||
-rw-r--r-- | include/Theme.hpp | 18 | ||||
-rw-r--r-- | include/gui/DropdownButton.hpp | 54 | ||||
-rw-r--r-- | include/gui/Utils.hpp | 13 | ||||
-rw-r--r-- | src/GsrInfo.cpp | 179 | ||||
-rw-r--r-- | src/Theme.cpp | 34 | ||||
-rw-r--r-- | src/gui/Button.cpp | 3 | ||||
-rw-r--r-- | src/gui/ComboBox.cpp | 44 | ||||
-rw-r--r-- | src/gui/DropdownButton.cpp | 181 | ||||
-rw-r--r-- | src/gui/Utils.cpp | 43 | ||||
-rw-r--r-- | src/gui/WidgetContainer.cpp | 5 | ||||
-rw-r--r-- | src/main.cpp | 104 |
13 files changed, 644 insertions, 102 deletions
@@ -9,3 +9,5 @@ Maybe change design to have black triangles appear and get larger until they fil All of these things should be done with vertex buffer, for real 3D. DISPLAY gamescope-0 + +Colorscheme should follow graphics card in use. On nvidia use nvidia green, on intel use intel blue and on amd use amd red.
\ No newline at end of file diff --git a/include/GsrInfo.hpp b/include/GsrInfo.hpp new file mode 100644 index 0000000..e029919 --- /dev/null +++ b/include/GsrInfo.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include <string> +#include <vector> + +#include <mglpp/system/vec.hpp> + +namespace gsr { + struct SupportedVideoCodecs { + bool h264 = false; + bool hevc = false; + bool av1 = false; + bool vp8 = false; + bool vp9 = false; + }; + + struct GsrMonitor { + std::string name; + mgl::vec2i size; + }; + + struct SupportedCaptureOptions { + bool window = false; + bool focused = false; + bool screen = false; + bool portal = false; + std::vector<GsrMonitor> monitors; + }; + + enum class DisplayServer { + UNKNOWN, + X11, + WAYLAND + }; + + struct SystemInfo { + DisplayServer display_server = DisplayServer::UNKNOWN; + }; + + enum class GpuVendor { + UNKNOWN, + AMD, + INTEL, + NVIDIA + }; + + struct GpuInfo { + GpuVendor vendor = GpuVendor::UNKNOWN; + }; + + struct GsrInfo { + SystemInfo system_info; + GpuInfo gpu_info; + SupportedVideoCodecs supported_video_codecs; + SupportedCaptureOptions supported_capture_options; + }; + + enum class GsrInfoExitStatus { + OK, + FAILED_TO_RUN_COMMAND, + OPENGL_FAILED, + NO_DRM_CARD + }; + + GsrInfoExitStatus get_gpu_screen_recorder_info(GsrInfo *gsr_info); +}
\ No newline at end of file diff --git a/include/Theme.hpp b/include/Theme.hpp new file mode 100644 index 0000000..182d264 --- /dev/null +++ b/include/Theme.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include <mglpp/graphics/Color.hpp> + +namespace gsr { + struct GsrInfo; + + struct Theme { + Theme() = default; + Theme(const Theme&) = delete; + Theme& operator=(const Theme&) = delete; + + mgl::Color tint_color = mgl::Color(118, 185, 0); + }; + + void init_theme(const gsr::GsrInfo &gsr_info); + const Theme& get_theme(); +}
\ No newline at end of file diff --git a/include/gui/DropdownButton.hpp b/include/gui/DropdownButton.hpp new file mode 100644 index 0000000..bcf769c --- /dev/null +++ b/include/gui/DropdownButton.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "Widget.hpp" +#include <string> +#include <functional> +#include <vector> +#include <mglpp/graphics/Text.hpp> +#include <mglpp/graphics/Sprite.hpp> + +namespace gsr { + class DropdownButton : public Widget { + public: + DropdownButton(mgl::Font *title_font, mgl::Font *description_font, const char *title, const char *description_activated, const char *description_deactivated, mgl::Texture *icon_texture, mgl::vec2f size); + DropdownButton(const DropdownButton&) = delete; + DropdownButton& operator=(const DropdownButton&) = delete; + + bool on_event(mgl::Event &event, mgl::Window &window) override; + void draw(mgl::Window &window) override; + + void add_item(const std::string &text, const std::string &id); + void set_item_label(const std::string &id, const std::string &new_label); + + void set_activated(bool activated); + + mgl::vec2f get_size(); + + std::function<void(const std::string &id)> on_click; + private: + void update_if_dirty(); + private: + struct Item { + mgl::Text text; + std::string id; + }; + + std::vector<Item> items; + mgl::Font *title_font; + mgl::Font *description_font; + mgl::vec2f size; + bool mouse_inside = false; + bool show_dropdown = false; + bool dirty = true; + mgl::vec2f max_size; + int mouse_inside_item = -1; + + mgl::Text title; + mgl::Text description; + mgl::Sprite icon_sprite; + + std::string description_activated; + std::string description_deactivated; + bool activated = false; + }; +}
\ No newline at end of file diff --git a/include/gui/Utils.hpp b/include/gui/Utils.hpp new file mode 100644 index 0000000..fe5ee49 --- /dev/null +++ b/include/gui/Utils.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include <mglpp/system/vec.hpp> +#include <mglpp/graphics/Color.hpp> + +namespace mgl { + class Window; +} + +namespace gsr { + // Inner border + void draw_rectangle_outline(mgl::Window &window, mgl::vec2f pos, mgl::vec2f size, mgl::Color color, float border_size); +}
\ No newline at end of file diff --git a/src/GsrInfo.cpp b/src/GsrInfo.cpp new file mode 100644 index 0000000..1534363 --- /dev/null +++ b/src/GsrInfo.cpp @@ -0,0 +1,179 @@ +#include "../include/GsrInfo.hpp" +#include <string.h> +#include <functional> + +namespace gsr { + using StringSplitCallback = std::function<bool(std::string_view line)>; + + static void string_split_char(const std::string &str, char delimiter, StringSplitCallback callback_func) { + size_t index = 0; + while(index < str.size()) { + size_t new_index = str.find(delimiter, index); + if(new_index == std::string::npos) + new_index = str.size(); + + if(!callback_func({str.data() + index, new_index - index})) + break; + + index = new_index + 1; + } + } + + static void parse_system_info_line(GsrInfo *gsr_info, const std::string &line) { + const size_t space_index = line.find(' '); + if(space_index == std::string::npos) + return; + + const std::string_view attribute_name = {line.c_str(), space_index}; + const std::string_view attribute_value = {line.c_str() + space_index + 1, line.size() - (space_index + 1)}; + if(attribute_name == "display_server") { + if(attribute_value == "x11") + gsr_info->system_info.display_server = DisplayServer::X11; + else if(attribute_value == "wayland") + gsr_info->system_info.display_server = DisplayServer::WAYLAND; + } + } + + static void parse_gpu_info_line(GsrInfo *gsr_info, const std::string &line) { + const size_t space_index = line.find(' '); + if(space_index == std::string::npos) + return; + + const std::string_view attribute_name = {line.c_str(), space_index}; + const std::string_view attribute_value = {line.c_str() + space_index + 1, line.size() - (space_index + 1)}; + if(attribute_name == "vendor") { + if(attribute_value == "amd") + gsr_info->gpu_info.vendor = GpuVendor::AMD; + else if(attribute_value == "intel") + gsr_info->gpu_info.vendor = GpuVendor::INTEL; + else if(attribute_value == "nvidia") + gsr_info->gpu_info.vendor = GpuVendor::NVIDIA; + } + } + + static void parse_video_codecs_line(GsrInfo *gsr_info, const std::string &line) { + if(line == "h264") + gsr_info->supported_video_codecs.h264 = true; + else if(line == "hevc") + gsr_info->supported_video_codecs.hevc = true; + else if(line == "av1") + gsr_info->supported_video_codecs.av1 = true; + else if(line == "vp8") + gsr_info->supported_video_codecs.vp8 = true; + else if(line == "vp9") + gsr_info->supported_video_codecs.vp9 = true; + } + + static GsrMonitor capture_option_line_to_monitor(const std::string &line) { + size_t space_index = line.find(' '); + if(space_index == std::string::npos) + return { line, {0, 0} }; + + mgl::vec2i size = {0, 0}; + if(sscanf(line.c_str() + space_index + 1, "%dx%d", &size.x, &size.y) != 2) + size = {0, 0}; + + return { line.substr(0, space_index), size }; + } + + static void parse_capture_options_line(GsrInfo *gsr_info, const std::string &line) { + if(line == "window") + gsr_info->supported_capture_options.window = true; + else if(line == "focused") + gsr_info->supported_capture_options.focused = true; + else if(line == "screen") + gsr_info->supported_capture_options.screen = true; + else if(line == "portal") + gsr_info->supported_capture_options.portal = true; + else + gsr_info->supported_capture_options.monitors.push_back(capture_option_line_to_monitor(line)); + } + + enum class GsrInfoSection { + UNKNOWN, + SYSTEM_INFO, + GPU_INFO, + VIDEO_CODECS, + CAPTURE_OPTIONS + }; + + static bool starts_with(const std::string &str, const char *substr) { + size_t len = strlen(substr); + return str.size() >= len && memcmp(str.data(), substr, len) == 0; + } + + GsrInfoExitStatus get_gpu_screen_recorder_info(GsrInfo *gsr_info) { + *gsr_info = GsrInfo{}; + + FILE *f = popen("gpu-screen-recorder --info", "r"); + if(!f) { + fprintf(stderr, "error: 'gpu-screen-recorder --info' failed\n"); + return GsrInfoExitStatus::FAILED_TO_RUN_COMMAND; + } + + char output[8192]; + ssize_t bytes_read = fread(output, 1, sizeof(output) - 1, f); + if(bytes_read < 0 || ferror(f)) { + fprintf(stderr, "error: failed to read 'gpu-screen-recorder --info' output\n"); + pclose(f); + return GsrInfoExitStatus::FAILED_TO_RUN_COMMAND; + } + output[bytes_read] = '\0'; + + GsrInfoSection section = GsrInfoSection::UNKNOWN; + string_split_char(output, '\n', [&](std::string_view line) { + const std::string line_str(line.data(), line.size()); + + if(starts_with(line_str, "section=")) { + const char *section_name = line_str.c_str() + 8; + if(strcmp(section_name, "system_info") == 0) + section = GsrInfoSection::SYSTEM_INFO; + else if(strcmp(section_name, "gpu_info") == 0) + section = GsrInfoSection::GPU_INFO; + else if(strcmp(section_name, "video_codecs") == 0) + section = GsrInfoSection::VIDEO_CODECS; + else if(strcmp(section_name, "capture_options") == 0) + section = GsrInfoSection::CAPTURE_OPTIONS; + else + section = GsrInfoSection::UNKNOWN; + return true; + } + + switch(section) { + case GsrInfoSection::UNKNOWN: { + break; + } + case GsrInfoSection::SYSTEM_INFO: { + parse_system_info_line(gsr_info, line_str); + break; + } + case GsrInfoSection::GPU_INFO: { + parse_gpu_info_line(gsr_info, line_str); + break; + } + case GsrInfoSection::VIDEO_CODECS: { + parse_video_codecs_line(gsr_info, line_str); + break; + } + case GsrInfoSection::CAPTURE_OPTIONS: { + parse_capture_options_line(gsr_info, line_str); + break; + } + } + + return true; + }); + + int status = pclose(f); + if(WIFEXITED(status)) { + switch(WEXITSTATUS(status)) { + case 0: return GsrInfoExitStatus::OK; + case 22: return GsrInfoExitStatus::OPENGL_FAILED; + case 23: return GsrInfoExitStatus::NO_DRM_CARD; + default: return GsrInfoExitStatus::FAILED_TO_RUN_COMMAND; + } + } + + return GsrInfoExitStatus::FAILED_TO_RUN_COMMAND; + } +}
\ No newline at end of file diff --git a/src/Theme.cpp b/src/Theme.cpp new file mode 100644 index 0000000..0f44126 --- /dev/null +++ b/src/Theme.cpp @@ -0,0 +1,34 @@ +#include "../include/Theme.hpp" +#include "../include/GsrInfo.hpp" +#include <assert.h> + +namespace gsr { + static Theme theme; + static bool initialized = false; + + void init_theme(const gsr::GsrInfo &gsr_info) { + switch(gsr_info.gpu_info.vendor) { + case gsr::GpuVendor::UNKNOWN: { + break; + } + case gsr::GpuVendor::AMD: { + theme.tint_color = mgl::Color(221, 0, 49); + break; + } + case gsr::GpuVendor::INTEL: { + theme.tint_color = mgl::Color(8, 109, 183); + break; + } + case gsr::GpuVendor::NVIDIA: { + theme.tint_color = mgl::Color(118, 185, 0); + break; + } + } + initialized = true; + } + + const Theme& get_theme() { + assert(initialized); + return theme; + } +}
\ No newline at end of file diff --git a/src/gui/Button.cpp b/src/gui/Button.cpp index b9d6d7c..3cad31f 100644 --- a/src/gui/Button.cpp +++ b/src/gui/Button.cpp @@ -1,4 +1,5 @@ #include "../../include/gui/Button.hpp" +#include "../../include/Theme.hpp" #include <mglpp/graphics/Rectangle.hpp> #include <mglpp/window/Window.hpp> #include <mglpp/window/Event.hpp> @@ -40,7 +41,7 @@ namespace gsr { } const int border_size = 5; - const mgl::Color border_color(118, 185, 0); + const mgl::Color border_color = gsr::get_theme().tint_color; // Green line at top { diff --git a/src/gui/ComboBox.cpp b/src/gui/ComboBox.cpp index 00e8bc3..dd683e1 100644 --- a/src/gui/ComboBox.cpp +++ b/src/gui/ComboBox.cpp @@ -1,4 +1,6 @@ #include "../../include/gui/ComboBox.hpp" +#include "../../include/gui/Utils.hpp" +#include "../../include/Theme.hpp" #include <mglpp/graphics/Rectangle.hpp> #include <mglpp/graphics/Font.hpp> #include <mglpp/window/Window.hpp> @@ -46,40 +48,6 @@ namespace gsr { return true; } - static void draw_rectangle_outline(mgl::Window &window, mgl::vec2f pos, mgl::vec2f size, mgl::Color color, float border_size) { - // Green line at top - { - mgl::Rectangle rect({ size.x, border_size }); - rect.set_position(pos); - rect.set_color(color); - window.draw(rect); - } - - // Green line at bottom - { - mgl::Rectangle rect({ size.x, border_size }); - rect.set_position(pos + mgl::vec2f(0.0f, size.y - border_size)); - rect.set_color(color); - window.draw(rect); - } - - // Green line at left - { - mgl::Rectangle rect({ border_size, size.y - border_size * 2 }); - rect.set_position(pos + mgl::vec2f(0, border_size)); - rect.set_color(color); - window.draw(rect); - } - - // Green line at right - { - mgl::Rectangle rect({ border_size, size.y - border_size * 2 }); - rect.set_position(pos + mgl::vec2f(size.x - border_size, border_size)); - rect.set_color(color); - window.draw(rect); - } - } - void ComboBox::draw(mgl::Window &window) { update_if_dirty(); @@ -102,10 +70,10 @@ namespace gsr { mgl::vec2f pos = position + mgl::vec2f(padding_left, padding_top); Item &item = items[selected_item]; - item.text.set_position(pos); + item.text.set_position(pos.floor()); if(show_dropdown) { const int border_size = 3; - const mgl::Color border_color(118, 185, 0); + const mgl::Color border_color = gsr::get_theme().tint_color; draw_rectangle_outline(window, pos - mgl::vec2f(padding_left, padding_top), item_size, border_color, border_size); } window.draw(item.text); @@ -113,7 +81,7 @@ namespace gsr { for(size_t i = 0; i < items.size(); ++i) { Item &item = items[i]; - item.text.set_position(pos); + item.text.set_position(pos.floor()); const mgl::FloatRect text_bounds = item.text.get_bounds(); if(show_dropdown) { @@ -121,7 +89,7 @@ namespace gsr { inside = mgl::FloatRect(text_bounds.position - mgl::vec2f(padding_left, padding_top), item_size).contains({ (float)mouse_pos.x, (float)mouse_pos.y }); if(inside) { mgl::Rectangle item_background(text_bounds.position - mgl::vec2f(padding_left, padding_top), item_size); - item_background.set_color(mgl::Color(118, 185, 0)); + item_background.set_color(gsr::get_theme().tint_color); window.draw(item_background); } else { /*const int border_size = 3; diff --git a/src/gui/DropdownButton.cpp b/src/gui/DropdownButton.cpp new file mode 100644 index 0000000..9610e26 --- /dev/null +++ b/src/gui/DropdownButton.cpp @@ -0,0 +1,181 @@ +#include "../../include/gui/DropdownButton.hpp" +#include "../../include/gui/Utils.hpp" +#include "../../include/Theme.hpp" +#include <mglpp/graphics/Rectangle.hpp> +#include <mglpp/graphics/Texture.hpp> +#include <mglpp/window/Window.hpp> +#include <mglpp/window/Event.hpp> +#include <mglpp/system/FloatRect.hpp> + +namespace gsr { + static const float padding_top = 10.0f; + static const float padding_bottom = 10.0f; + static const float padding_left = 10.0f; + static const float padding_right = 10.0f; + static const int border_size = 5; + + DropdownButton::DropdownButton(mgl::Font *title_font, mgl::Font *description_font, const char *title, const char *description_activated, const char *description_deactivated, mgl::Texture *icon_texture, mgl::vec2f size) : + title_font(title_font), description_font(description_font), size(size), title(title, *title_font), description(description_deactivated, *description_font), + description_activated(description_activated), description_deactivated(description_deactivated) + { + if(icon_texture && icon_texture->is_valid()) { + icon_sprite.set_texture(icon_texture); + icon_sprite.set_height((int)(size.y * 0.5f)); + } + this->description.set_color(mgl::Color(150, 150, 150)); + } + + bool DropdownButton::on_event(mgl::Event &event, mgl::Window&) { + if(event.type == mgl::Event::MouseMoved) { + const mgl::vec2f collision_margin(1.0f, 1.0f); // Makes sure that multiple buttons that are next to each other wont activate at the same time when the cursor is right between them + const bool inside = mgl::FloatRect(position + collision_margin, size - collision_margin).contains({ (float)event.mouse_move.x, (float)event.mouse_move.y }); + if(mouse_inside && !inside) { + mouse_inside = false; + } else if(!mouse_inside && inside) { + mouse_inside = true; + } + } else if(event.type == mgl::Event::MouseButtonPressed) { + const bool clicked_inside = mouse_inside; + show_dropdown = clicked_inside; + if(on_click && mouse_inside_item >= 0 && mouse_inside_item < (int)items.size()) + on_click(items[mouse_inside_item].id); + } + return true; + } + + void DropdownButton::draw(mgl::Window &window) { + update_if_dirty(); + + if(show_dropdown) { + // Background + { + mgl::Rectangle rect(size); + rect.set_position(position); + rect.set_color(mgl::Color(0, 0, 0, 255)); + window.draw(rect); + } + + const mgl::Color border_color = gsr::get_theme().tint_color; + + // Green line at top + { + mgl::Rectangle rect({ size.x, border_size }); + rect.set_position(position); + rect.set_color(border_color); + window.draw(rect); + } + } else if(mouse_inside) { + // Background + { + mgl::Rectangle rect(size); + rect.set_position(position); + rect.set_color(mgl::Color(0, 0, 0, 255)); + window.draw(rect); + } + + const mgl::Color border_color = gsr::get_theme().tint_color; + draw_rectangle_outline(window, position, size, border_color, border_size); + } else { + // Background + mgl::Rectangle rect(size); + rect.set_position(position); + rect.set_color(mgl::Color(0, 0, 0, 220)); + window.draw(rect); + } + + const int text_margin = size.y * 0.085; + + const auto title_bounds = title.get_bounds(); + title.set_position((position + mgl::vec2f(size.x * 0.5f - title_bounds.size.x * 0.5f, text_margin)).floor()); + window.draw(title); + + const auto description_bounds = description.get_bounds(); + description.set_position((position + mgl::vec2f(size.x * 0.5f - description_bounds.size.x * 0.5f, size.y - description_bounds.size.y - text_margin)).floor()); + window.draw(description); + + if(icon_sprite.get_texture()->is_valid()) { + icon_sprite.set_position((position + size * 0.5f - icon_sprite.get_size() * 0.5f).floor()); + window.draw(icon_sprite); + } + + mouse_inside_item = -1; + if(show_dropdown) { + const mgl::vec2i mouse_pos = window.get_mouse_position(); + + mgl::Rectangle dropdown_bg(max_size); + dropdown_bg.set_position(position + mgl::vec2f(0.0f, size.y)); + dropdown_bg.set_color(mgl::Color(0, 0, 0)); + window.draw(dropdown_bg); + + mgl::vec2f item_position = dropdown_bg.get_position(); + for(size_t i = 0; i < items.size(); ++i) { + auto &item = items[i]; + const auto text_bounds = item.text.get_bounds(); + const float item_height = padding_top + text_bounds.size.y + padding_bottom; + + if(mouse_inside_item == -1) { + const mgl::vec2f item_size(max_size.x, item_height); + const bool inside = mgl::FloatRect(item_position, item_size).contains({ (float)mouse_pos.x, (float)mouse_pos.y }); + if(inside) { + draw_rectangle_outline(window, item_position, item_size, gsr::get_theme().tint_color, 5); + mouse_inside_item = i; + } + } + + item.text.set_position((item_position + mgl::vec2f(padding_left, item_height * 0.5f - text_bounds.size.y * 0.5f)).floor()); + window.draw(item.text); + item_position.y += item_height; + } + } + } + + void DropdownButton::add_item(const std::string &text, const std::string &id) { + items.push_back({mgl::Text(text, *title_font), id}); + dirty = true; + } + + void DropdownButton::set_item_label(const std::string &id, const std::string &new_label) { + for(auto &item : items) { + if(item.id == id) { + item.text.set_string(new_label); + dirty = true; + return; + } + } + } + + void DropdownButton::set_activated(bool activated) { + if(this->activated == activated) + return; + + this->activated = activated; + + if(activated) { + description = mgl::Text(description_activated, *description_font); + description.set_color(get_theme().tint_color); + icon_sprite.set_color(get_theme().tint_color); + } else { + description = mgl::Text(description_deactivated, *description_font); + description.set_color(mgl::Color(150, 150, 150)); + icon_sprite.set_color(mgl::Color(255, 255, 255)); + } + } + + void DropdownButton::update_if_dirty() { + if(!dirty) + return; + + max_size = { size.x, 0.0f }; + for(Item &item : items) { + const mgl::vec2f bounds = item.text.get_bounds().size; + max_size.x = std::max(max_size.x, bounds.x + padding_left + padding_right); + max_size.y += bounds.y + padding_top + padding_bottom; + } + dirty = false; + } + + mgl::vec2f DropdownButton::get_size() { + update_if_dirty(); + return size; + } +}
\ No newline at end of file diff --git a/src/gui/Utils.cpp b/src/gui/Utils.cpp new file mode 100644 index 0000000..20c7b73 --- /dev/null +++ b/src/gui/Utils.cpp @@ -0,0 +1,43 @@ +#include "../../include/gui/Utils.hpp" +#include <mglpp/window/Window.hpp> +#include <mglpp/graphics/Rectangle.hpp> + +namespace gsr { + // TODO: Use vertices to make it one draw call + void draw_rectangle_outline(mgl::Window &window, mgl::vec2f pos, mgl::vec2f size, mgl::Color color, float border_size) { + pos = pos.floor(); + size = size.floor(); + border_size = (int)border_size; + // Green line at top + { + mgl::Rectangle rect({ size.x, border_size }); + rect.set_position(pos); + rect.set_color(color); + window.draw(rect); + } + + // Green line at bottom + { + mgl::Rectangle rect({ size.x, border_size }); + rect.set_position(pos + mgl::vec2f(0.0f, size.y - border_size)); + rect.set_color(color); + window.draw(rect); + } + + // Green line at left + { + mgl::Rectangle rect({ border_size, size.y - border_size * 2 }); + rect.set_position(pos + mgl::vec2f(0, border_size)); + rect.set_color(color); + window.draw(rect); + } + + // Green line at right + { + mgl::Rectangle rect({ border_size, size.y - border_size * 2 }); + rect.set_position(pos + mgl::vec2f(size.x - border_size, border_size)); + rect.set_color(color); + window.draw(rect); + } + } +}
\ No newline at end of file diff --git a/src/gui/WidgetContainer.cpp b/src/gui/WidgetContainer.cpp index ab97b5b..8824d1a 100644 --- a/src/gui/WidgetContainer.cpp +++ b/src/gui/WidgetContainer.cpp @@ -42,10 +42,11 @@ namespace gsr { Widget *widget = *it; if(widget->move_to_top) { widget->move_to_top = false; - if(widgets.back() != widget) { + std::swap(*it, widgets.back()); + /*if(widgets.back() != widget) { widgets.erase(it); widgets.push_back(widget); - } + }*/ } } diff --git a/src/main.cpp b/src/main.cpp index 0fb7b95..0ecd715 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,10 @@ #include "../include/gui/WidgetContainer.hpp" -#include "../include/gui/Button.hpp" +#include "../include/gui/DropdownButton.hpp" #include "../include/gui/ComboBox.hpp" #include "../include/Process.hpp" +#include "../include/Theme.hpp" +#include "../include/GsrInfo.hpp" #include <stdio.h> #include <stdlib.h> @@ -138,6 +140,15 @@ int main(int argc, char **argv) { signal(SIGINT, sigint_handler); + gsr::GsrInfo gsr_info; + // TODO: + gsr::GsrInfoExitStatus gsr_info_exit_status = gsr::get_gpu_screen_recorder_info(&gsr_info); + if(gsr_info_exit_status != gsr::GsrInfoExitStatus::OK) { + fprintf(stderr, "error: failed to get gpu-screen-recorder info\n"); + exit(1); + } + gsr::init_theme(gsr_info); + std::string program_root_dir = dirname(argv[0]); if(!program_root_dir.empty() && program_root_dir.back() != '/') program_root_dir += '/'; @@ -225,10 +236,7 @@ int main(int argc, char **argv) { bg_screenshot_overlay.set_color(bg_color); struct MainButton { - mgl::Text title; - mgl::Text description; - mgl::Sprite icon; - std::unique_ptr<gsr::Button> button; + std::unique_ptr<gsr::DropdownButton> button; gsr::GsrMode mode; }; @@ -256,26 +264,17 @@ int main(int argc, char **argv) { &stream_button_texture }; - const int button_height = window_create_params.size.y / 6.0f; + const int button_height = window_create_params.size.y / 5.0f; const int button_width = button_height; std::vector<MainButton> main_buttons; for(int i = 0; i < 3; ++i) { - mgl::Text title(titles[i], {0.0f, 0.0f}, title_font); - title.set_color(mgl::Color(255, 255, 255)); - - mgl::Text description(descriptions_off[i], {0.0f, 0.0f}, font); - description.set_color(mgl::Color(150, 150, 150)); - - mgl::Sprite sprite(textures[i]); - sprite.set_height(button_height * 0.5f); - auto button = std::make_unique<gsr::Button>(mgl::vec2f(button_width, button_height)); + auto button = std::make_unique<gsr::DropdownButton>(&title_font, &font, titles[i], descriptions_on[i], descriptions_off[i], textures[i], mgl::vec2f(button_width, button_height)); + button->add_item("Start", "start"); + button->add_item("Settings", "settings"); MainButton main_button = { - std::move(title), - std::move(description), - std::move(sprite), std::move(button), gsr::GsrMode::Unknown }; @@ -285,7 +284,6 @@ int main(int argc, char **argv) { auto update_overlay_shape = [&](std::optional<gsr::GsrMode> gsr_mode = std::nullopt) { fprintf(stderr, "update overlay shape!\n"); - const int main_button_margin = button_height * 0.085;// * get_config().scale; const int spacing = 0;// * get_config().scale; const int combined_spacing = spacing * std::max(0, (int)main_buttons.size() - 1); @@ -303,37 +301,18 @@ int main(int argc, char **argv) { for(size_t i = 0; i < main_buttons.size(); ++i) { if(main_buttons[i].mode != gsr::GsrMode::Unknown && main_buttons[i].mode == gsr_mode.value()) { - main_buttons[i].description.set_string(descriptions_on[i]); - main_buttons[i].description.set_color(mgl::Color(118, 185, 0)); - main_buttons[i].icon.set_color(mgl::Color(118, 185, 0)); + main_buttons[i].button->set_activated(true); } else { - main_buttons[i].description.set_string(descriptions_off[i]); - main_buttons[i].description.set_color(mgl::Color(150, 150, 150)); - main_buttons[i].icon.set_color(mgl::Color(255, 255, 255)); + main_buttons[i].button->set_activated(false); } - main_buttons[i].title.set_position( - mgl::vec2f( - main_button_pos.x + per_button_width * 0.5f - main_buttons[i].title.get_bounds().size.x * 0.5f, - main_button_pos.y + main_button_margin).floor()); - - main_buttons[i].description.set_position( - mgl::vec2f( - main_button_pos.x + per_button_width * 0.5f - main_buttons[i].description.get_bounds().size.x * 0.5f, - main_button_pos.y + overlay_desired_size.y - main_buttons[i].description.get_bounds().size.y - main_button_margin).floor()); - - main_buttons[i].icon.set_position( - mgl::vec2f( - main_button_pos.x + per_button_width * 0.5f - main_buttons[i].icon.get_texture()->get_size().x * main_buttons[i].icon.get_scale().x * 0.5f, - main_button_pos.y + overlay_desired_size.y * 0.5f - main_buttons[i].icon.get_texture()->get_size().y * main_buttons[i].icon.get_scale().y * 0.5f).floor()); - main_buttons[i].button->set_position(main_button_pos.to_vec2f()); main_button_pos.x += per_button_width + combined_spacing; } }; // Replay - main_buttons[0].button->on_click = [&]() { + main_buttons[0].button->on_click = [&](const std::string &id) { /* char window_to_record_str[32]; snprintf(window_to_record_str, sizeof(window_to_record_str), "%ld", target_window); @@ -353,9 +332,12 @@ int main(int argc, char **argv) { // TODO: Monitor /tmp/gpu-screen-recorder and update ui to match state // Record - main_buttons[1].button->on_click = [&]() { - window.close(); - usleep(1000 * 50); // 50 milliseconds + main_buttons[1].button->on_click = [&](const std::string &id) { + if(id != "start") + return; + + // window.close(); + // usleep(1000 * 50); // 50 milliseconds pid_t gpu_screen_recorder_process = -1; gsr::GsrMode gsr_mode = gsr::GsrMode::Unknown; @@ -366,12 +348,13 @@ int main(int argc, char **argv) { perror("waitpid failed"); /* Ignore... */ } - window.set_visible(false); - window.close(); - return; + // window.set_visible(false); + // window.close(); + // return; //exit(0); - //update_overlay_shape(gsr::GsrMode::Unknown); - //return; + update_overlay_shape(gsr::GsrMode::Unknown); + main_buttons[1].button->set_item_label(id, "Start"); + return; } const char *args[] = { @@ -382,10 +365,14 @@ int main(int argc, char **argv) { nullptr }; gsr::exec_program_daemonized(args); - //update_overlay_shape(gsr::GsrMode::Record); + update_overlay_shape(gsr::GsrMode::Record); + main_buttons[1].button->set_item_label(id, "Stop"); //exit(0); - window.set_visible(false); - window.close(); + // window.set_visible(false); + // window.close(); + + // TODO: Show notification with args: + // "Recording has started" 3.0 ./images/record.png 76b900 }; main_buttons[1].mode = gsr::GsrMode::Record; @@ -415,11 +402,11 @@ int main(int argc, char **argv) { //XGrabServer(display); - mgl::Rectangle top_bar_background(mgl::vec2f(window.get_size().x, window.get_size().y*0.05f).floor()); + mgl::Rectangle top_bar_background(mgl::vec2f(window.get_size().x, window.get_size().y*0.06f).floor()); top_bar_background.set_color(mgl::Color(0, 0, 0, 220)); mgl::Text top_bar_text("GPU Screen Recorder", top_bar_font); - //top_bar_text.set_color(mgl::Color(118, 185, 0)); + //top_bar_text.set_color(gsr::get_theme().tint_color); top_bar_text.set_position((top_bar_background.get_position() + top_bar_background.get_size()*0.5f - top_bar_text.get_bounds().size*0.5f).floor()); // gsr::ComboBox record_area_box(&title_font); @@ -458,7 +445,7 @@ int main(int argc, char **argv) { // framerate_title.set_position(mgl::vec2f(framerate_box.get_position().x, framerate_box.get_position().y - title_font.get_character_size() - 10.0f)); mgl::Texture close_texture; - if(!close_texture.load_from_file("images/cross.png", {false, false, false})) + if(!close_texture.load_from_file("images/cross.png")) startup_error("failed to load texture: images/cross.png"); mgl::Sprite close_sprite(&close_texture); @@ -489,7 +476,7 @@ int main(int argc, char **argv) { const float settings_topline_thickness = 5.0f; mgl::Rectangle settings_topline(settings_background.get_position() - mgl::vec2f(0.0f, settings_topline_thickness), mgl::vec2f(settings_background.get_size().x, settings_topline_thickness)); - settings_topline.set_color(mgl::Color(118, 185, 0)); + settings_topline.set_color(gsr::get_theme().tint_color); */ mgl::Clock state_update_timer; @@ -517,11 +504,6 @@ int main(int argc, char **argv) { // window.draw(video_quality_title); // window.draw(framerate_title); widget_container.draw(window); - for(auto &main_button : main_buttons) { - window.draw(main_button.icon); - window.draw(main_button.title); - window.draw(main_button.description); - } window.draw(top_bar_background); window.draw(top_bar_text); window.draw(logo_sprite); |