Add widgets for settings page, add list to auto position widgets

This commit is contained in:
dec05eba
2024-08-02 23:38:23 +02:00
parent 7c4af06d95
commit 2869ef7cec
18 changed files with 348 additions and 173 deletions

4
TODO
View File

@@ -10,4 +10,6 @@ Maybe change design to have black triangles appear and get larger until they fil
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.
Colorscheme should follow graphics card in use. On nvidia use nvidia green, on intel use intel blue and on amd use amd red.
Optimize list/page when having a few items in it (dont use vector<unique_ptr<Widget>>).

View File

@@ -16,7 +16,7 @@ namespace gsr {
bool on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) override;
void draw(mgl::Window &window, mgl::vec2f offset) override;
mgl::vec2f get_size() const { return size; }
mgl::vec2f get_size() override { return size; }
std::function<void()> on_click;
private:

View File

@@ -17,7 +17,7 @@ namespace gsr {
void add_item(const std::string &text, const std::string &id);
mgl::vec2f get_size();
mgl::vec2f get_size() override;
private:
void update_if_dirty();
private:

View File

@@ -22,7 +22,7 @@ namespace gsr {
void set_activated(bool activated);
mgl::vec2f get_size();
mgl::vec2f get_size() override;
std::function<void(const std::string &id)> on_click;
private:

View File

@@ -16,7 +16,7 @@ namespace gsr {
bool on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) override;
void draw(mgl::Window &window, mgl::vec2f offset) override;
mgl::vec2f get_size();
mgl::vec2f get_size() override;
private:
mgl::Text text;
};

28
include/gui/List.hpp Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include "Widget.hpp"
#include <vector>
#include <memory>
namespace gsr {
class List : public Widget {
public:
enum class Orientation {
VERTICAL,
HORIZONTAL
};
List(Orientation orientation);
List(const List&) = delete;
List& operator=(const List&) = delete;
bool on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) override;
void draw(mgl::Window &window, mgl::vec2f offset) override;
void add_widget(std::unique_ptr<Widget> widget);
mgl::vec2f get_size() override;
protected:
std::vector<std::unique_ptr<Widget>> widgets;
Orientation orientation;
};
}

View File

@@ -12,7 +12,7 @@ namespace gsr {
bool on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) override;
void draw(mgl::Window &window, mgl::vec2f offset) override;
mgl::vec2f get_size() const { return size; }
mgl::vec2f get_size() override { return size; }
private:
float get_border_size(mgl::Window &window) const;
private:

View File

@@ -12,7 +12,7 @@ namespace gsr {
bool on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) override;
void draw(mgl::Window &window, mgl::vec2f offset) override;
mgl::vec2f get_size() const { return size; }
mgl::vec2f get_size() override { return size; }
private:
mgl::vec2f size;
};

View File

@@ -11,6 +11,8 @@ namespace gsr {
class Widget {
friend class StaticPage;
friend class ScrollablePage;
friend class List;
friend class Page;
public:
Widget();
Widget(const Widget&) = delete;
@@ -23,8 +25,13 @@ namespace gsr {
virtual void set_position(mgl::vec2f position);
virtual mgl::vec2f get_position() const;
virtual mgl::vec2f get_size() = 0;
protected:
void set_widget_as_selected_in_parent();
void remove_widget_as_selected_in_parent();
protected:
mgl::vec2f position;
bool move_to_top = false;
Widget *parent_widget = nullptr;
Widget *selected_child_widget = nullptr;
};
}

View File

@@ -33,6 +33,7 @@ namespace gsr {
if(mgl::FloatRect(pos - mgl::vec2f(padding_left, padding_top), item_size).contains(mouse_pos)) {
selected_item = i;
show_dropdown = false;
remove_widget_as_selected_in_parent();
return false;
}
pos.y += text_bounds.size.y + padding_top + padding_bottom;
@@ -42,9 +43,13 @@ namespace gsr {
if(mgl::FloatRect(draw_pos, item_size).contains(mouse_pos)) {
show_dropdown = !show_dropdown;
if(show_dropdown)
move_to_top = true;
set_widget_as_selected_in_parent();
else
remove_widget_as_selected_in_parent();
return false;
} else {
show_dropdown = false;
remove_widget_as_selected_in_parent();
}
}
return true;

View File

@@ -37,9 +37,20 @@ namespace gsr {
}
} else if(event.type == mgl::Event::MouseButtonPressed) {
const bool clicked_inside = mouse_inside;
if(show_dropdown && clicked_inside && mouse_inside_item == -1) {
show_dropdown = false;
remove_widget_as_selected_in_parent();
return false;
}
show_dropdown = clicked_inside;
if(show_dropdown)
move_to_top = true;
set_widget_as_selected_in_parent();
else
remove_widget_as_selected_in_parent();
if(mouse_inside_item >= 0 && mouse_inside_item < (int)items.size()) {
if(on_click)
on_click(items[mouse_inside_item].id);

85
src/gui/List.cpp Normal file
View File

@@ -0,0 +1,85 @@
#include "../../include/gui/List.hpp"
namespace gsr {
// TODO: Make this modifiable, multiple by window size.
// TODO: Add homogeneous option, using a specified max size of this list.
static const mgl::vec2f spacing(30.0f, 10.0f);
List::List(Orientation orientation) : orientation(orientation) {}
bool List::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f) {
if(selected_child_widget) {
if(!selected_child_widget->on_event(event, window, mgl::vec2f(0.0f, 0.0f)))
return false;
}
// Process widgets by visibility (backwards)
for(auto it = widgets.rbegin(), end = widgets.rend(); it != end; ++it) {
// Ignore offset because widgets are positioned with offset in ::draw, this solution is simpler
if(it->get() != selected_child_widget) {
if(!(*it)->on_event(event, window, mgl::vec2f(0.0f, 0.0f)))
return false;
}
}
return true;
}
void List::draw(mgl::Window &window, mgl::vec2f offset) {
mgl::vec2f draw_pos = position + offset;
// TODO: Do same vertical/horizontal alignment for items
switch(orientation) {
case Orientation::VERTICAL: {
for(auto &widget : widgets) {
widget->set_position(draw_pos);
if(widget.get() != selected_child_widget)
widget->draw(window, mgl::vec2f(0.0f, 0.0f));
draw_pos.y += widget->get_size().y + spacing.y;
}
break;
}
case Orientation::HORIZONTAL: {
for(auto &widget : widgets) {
widget->set_position(draw_pos);
if(widget.get() != selected_child_widget)
widget->draw(window, mgl::vec2f(0.0f, 0.0f));
draw_pos.x += widget->get_size().x + spacing.x;
}
break;
}
}
if(selected_child_widget)
selected_child_widget->draw(window, mgl::vec2f(0.0f, 0.0f));
}
void List::add_widget(std::unique_ptr<Widget> widget) {
widget->parent_widget = this;
widgets.push_back(std::move(widget));
}
// TODO: Cache result
mgl::vec2f List::get_size() {
mgl::vec2f size;
switch(orientation) {
case Orientation::VERTICAL: {
for(auto &widget : widgets) {
const auto widget_size = widget->get_size();
size.x = std::max(size.x, widget_size.x);
size.y += widget_size.y + spacing.y;
}
break;
}
case Orientation::HORIZONTAL: {
for(auto &widget : widgets) {
const auto widget_size = widget->get_size();
size.x += widget_size.x + spacing.x;
size.y = std::max(size.y, widget_size.y);
}
break;
}
}
return size;
}
}

View File

@@ -2,6 +2,7 @@
namespace gsr {
void Page::add_widget(std::unique_ptr<Widget> widget) {
widget->parent_widget = this;
widgets.push_back(std::move(widget));
}
}

View File

@@ -11,10 +11,17 @@ namespace gsr {
const mgl::vec2f draw_pos = position + offset;
offset = draw_pos + mgl::vec2f(0.0f, get_border_size(window)).floor();
if(selected_child_widget) {
if(!selected_child_widget->on_event(event, window, offset))
return false;
}
// Process widgets by visibility (backwards)
for(auto it = widgets.rbegin(), end = widgets.rend(); it != end; ++it) {
if(!(*it)->on_event(event, window, offset))
return false;
if(it->get() != selected_child_widget) {
if(!(*it)->on_event(event, window, offset))
return false;
}
}
return true;
@@ -44,15 +51,12 @@ namespace gsr {
window.draw(border);
for(auto &widget : widgets) {
if(widget->move_to_top) {
widget->move_to_top = false;
std::swap(widget, widgets.back());
}
if(widget.get() != selected_child_widget)
widget->draw(window, offset);
}
for(auto &widget : widgets) {
widget->draw(window, offset);
}
if(selected_child_widget)
selected_child_widget->draw(window, offset);
mgl_window_set_scissor(window.internal_window(), &prev_scissor);
}

View File

@@ -9,10 +9,17 @@ namespace gsr {
const mgl::vec2f draw_pos = position + offset;
offset = draw_pos;
if(selected_child_widget) {
if(!selected_child_widget->on_event(event, window, offset))
return false;
}
// Process widgets by visibility (backwards)
for(auto it = widgets.rbegin(), end = widgets.rend(); it != end; ++it) {
if(!(*it)->on_event(event, window, offset))
return false;
if(it->get() != selected_child_widget) {
if(!(*it)->on_event(event, window, offset))
return false;
}
}
return true;
@@ -32,15 +39,12 @@ namespace gsr {
mgl_window_set_scissor(window.internal_window(), &new_scissor);
for(auto &widget : widgets) {
if(widget->move_to_top) {
widget->move_to_top = false;
std::swap(widget, widgets.back());
}
if(widget.get() != selected_child_widget)
widget->draw(window, offset);
}
for(auto &widget : widgets) {
widget->draw(window, offset);
}
if(selected_child_widget)
selected_child_widget->draw(window, offset);
mgl_window_set_scissor(window.internal_window(), &prev_scissor);
}

View File

@@ -16,4 +16,18 @@ namespace gsr {
mgl::vec2f Widget::get_position() const {
return position;
}
void Widget::set_widget_as_selected_in_parent() {
if(parent_widget) {
parent_widget->selected_child_widget = this;
parent_widget->set_widget_as_selected_in_parent();
}
}
void Widget::remove_widget_as_selected_in_parent() {
if(parent_widget && parent_widget->selected_child_widget == this) {
parent_widget->selected_child_widget = nullptr;
parent_widget->remove_widget_as_selected_in_parent();
}
}
}

View File

@@ -5,6 +5,7 @@
#include "../include/gui/Button.hpp"
#include "../include/gui/ComboBox.hpp"
#include "../include/gui/Label.hpp"
#include "../include/gui/List.hpp"
#include "../include/Process.hpp"
#include "../include/Theme.hpp"
#include "../include/GsrInfo.hpp"
@@ -181,6 +182,162 @@ static std::string color_to_hex_str(mgl::Color color) {
return result;
}
static void add_widgets_to_settings_page(mgl::Font &title_font, mgl::vec2i window_size, mgl::vec2f settings_page_position, mgl::vec2f settings_page_size, gsr::Page *settings_page, gsr::Page *settings_content_page, const gsr::GsrInfo &gsr_info, const std::vector<gsr::AudioDevice> &audio_devices, std::function<void()> settings_back_button_callback) {
auto back_button = std::make_unique<gsr::Button>(&title_font, "Back", mgl::vec2f(window_size.x / 10, window_size.y / 15), gsr::get_theme().scrollable_page_bg_color);
back_button->set_position(settings_page_position + mgl::vec2f(settings_page_size.x + window_size.x / 50, 0.0f).floor());
back_button->on_click = settings_back_button_callback;
settings_page->add_widget(std::move(back_button));
auto settings_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
settings_list->set_position(mgl::vec2f(50.0f, 50.0f));
{
auto record_area_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
record_area_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Record area:", gsr::get_theme().text_color));
auto record_area_box = std::make_unique<gsr::ComboBox>(&title_font);
// TODO: Show options not supported but disable them
if(gsr_info.supported_capture_options.window)
record_area_box->add_item("Window", "window");
if(gsr_info.supported_capture_options.focused)
record_area_box->add_item("Focused window", "focused");
if(gsr_info.supported_capture_options.screen)
record_area_box->add_item("All monitors", "screen");
for(const auto &monitor : gsr_info.supported_capture_options.monitors) {
char name[256];
snprintf(name, sizeof(name), "%s (%dx%d)", monitor.name.c_str(), monitor.size.x, monitor.size.y);
record_area_box->add_item(name, monitor.name);
}
if(gsr_info.supported_capture_options.portal)
record_area_box->add_item("Desktop portal", "portal");
record_area_list->add_widget(std::move(record_area_box));
}
settings_list->add_widget(std::move(record_area_list));
auto audio_devices_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
audio_devices_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Audio:", gsr::get_theme().text_color));
auto audio_device_box = std::make_unique<gsr::ComboBox>(&title_font);
for(const auto &audio_device : audio_devices) {
audio_device_box->add_item(audio_device.description, audio_device.name);
}
audio_devices_list->add_widget(std::move(audio_device_box));
}
settings_list->add_widget(std::move(audio_devices_list));
auto quality_list = std::make_unique<gsr::List>(gsr::List::Orientation::HORIZONTAL);
{
auto video_quality_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
video_quality_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Video quality:", gsr::get_theme().text_color));
auto video_quality_box = std::make_unique<gsr::ComboBox>(&title_font);
video_quality_box->add_item("Medium", "medium");
video_quality_box->add_item("High (Recommended for live streaming)", "high");
video_quality_box->add_item("Very High (Recommended)", "very_high");
video_quality_box->add_item("Ultra", "ultra");
video_quality_list->add_widget(std::move(video_quality_box));
}
quality_list->add_widget(std::move(video_quality_list));
auto color_range_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
color_range_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Color range:", gsr::get_theme().text_color));
auto color_range_box = std::make_unique<gsr::ComboBox>(&title_font);
color_range_box->add_item("Limited", "limited");
color_range_box->add_item("Full", "full");
color_range_list->add_widget(std::move(color_range_box));
}
quality_list->add_widget(std::move(color_range_list));
auto framerate_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
framerate_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Frame rate:", gsr::get_theme().text_color));
auto framerate_box = std::make_unique<gsr::ComboBox>(&title_font);
framerate_box->add_item("60", "60");
framerate_box->add_item("30", "30");
framerate_list->add_widget(std::move(framerate_box));
}
quality_list->add_widget(std::move(framerate_list));
}
settings_list->add_widget(std::move(quality_list));
auto codec_list = std::make_unique<gsr::List>(gsr::List::Orientation::HORIZONTAL);
{
auto video_codec_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
video_codec_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Video codec:", gsr::get_theme().text_color));
auto video_codec_box = std::make_unique<gsr::ComboBox>(&title_font);
// TODO: Show options not supported but disable them
video_codec_box->add_item("Auto (Recommended)", "auto");
if(gsr_info.supported_video_codecs.h264)
video_codec_box->add_item("H264", "h264");
if(gsr_info.supported_video_codecs.hevc)
video_codec_box->add_item("HEVC", "hevc");
if(gsr_info.supported_video_codecs.av1)
video_codec_box->add_item("AV1", "av1");
if(gsr_info.supported_video_codecs.vp8)
video_codec_box->add_item("VP8", "vp8");
if(gsr_info.supported_video_codecs.vp9)
video_codec_box->add_item("VP9", "vp9");
// TODO: Add hdr options
video_codec_box->add_item("H264 Software Encoder (Slow, not recommended)", "h264_software");
video_codec_list->add_widget(std::move(video_codec_box));
}
codec_list->add_widget(std::move(video_codec_list));
auto audio_codec_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
audio_codec_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Audio codec:", gsr::get_theme().text_color));
auto audio_codec_box = std::make_unique<gsr::ComboBox>(&title_font);
audio_codec_box->add_item("Opus (Recommended)", "opus");
audio_codec_box->add_item("AAC", "aac");
audio_codec_list->add_widget(std::move(audio_codec_box));
}
codec_list->add_widget(std::move(audio_codec_list));
}
settings_list->add_widget(std::move(codec_list));
auto framerate_mode_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
framerate_mode_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Frame rate mode:", gsr::get_theme().text_color));
auto framerate_mode_box = std::make_unique<gsr::ComboBox>(&title_font);
framerate_mode_box->add_item("Auto (Recommended)", "auto");
framerate_mode_box->add_item("Constant", "cfr");
framerate_mode_box->add_item("Variable", "vfr");
framerate_mode_list->add_widget(std::move(framerate_mode_box));
}
settings_list->add_widget(std::move(framerate_mode_list));
auto file_list = std::make_unique<gsr::List>(gsr::List::Orientation::HORIZONTAL);
{
auto save_directory_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
save_directory_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Directory to save the video:", gsr::get_theme().text_color));
auto directory_selection_box = std::make_unique<gsr::ComboBox>(&title_font);
// TODO:
directory_selection_box->add_item("/home/dec05eba/Videos", "mp4");
save_directory_list->add_widget(std::move(directory_selection_box));
}
file_list->add_widget(std::move(save_directory_list));
auto container_list = std::make_unique<gsr::List>(gsr::List::Orientation::VERTICAL);
{
container_list->add_widget(std::make_unique<gsr::Label>(&title_font, "Container:", gsr::get_theme().text_color));
auto container_box = std::make_unique<gsr::ComboBox>(&title_font);
container_box->add_item("mp4", "mp4");
container_box->add_item("mkv", "matroska");
container_box->add_item("flv", "flv");
container_box->add_item("mov", "mov");
container_box->add_item("ts", "mpegts");
container_box->add_item("m3u8", "hls");
container_list->add_widget(std::move(container_box));
}
file_list->add_widget(std::move(container_list));
}
settings_list->add_widget(std::move(file_list));
}
settings_content_page->add_widget(std::move(settings_list));
}
int main(int argc, char **argv) {
if(argc != 1)
usage();
@@ -566,153 +723,10 @@ int main(int argc, char **argv) {
current_page = &front_page;
};
const mgl::vec2f page_widget_spacing{window_size.x / 100.0f, window_size.y / 40.0f};
for(int i = 0; i < num_settings_pages; ++i) {
mgl::vec2f settings_page_widget_pos{50.0f, 50.0f};
gsr::Page *settings_page = settings_pages[i];
gsr::Page *settings_content_page = settings_content_pages[i];
auto back_button = std::make_unique<gsr::Button>(&title_font, "Back", mgl::vec2f(window_size.x / 10, window_size.y / 15), gsr::get_theme().scrollable_page_bg_color);
back_button->set_position(settings_page_position + mgl::vec2f(settings_page_size.x + window_size.x / 50, 0.0f).floor());
back_button->on_click = settings_back_button_callback;
settings_page->add_widget(std::move(back_button));
auto record_area_label = std::make_unique<gsr::Label>(&title_font, "Record area:", gsr::get_theme().text_color);
record_area_label->set_position(settings_page_widget_pos);
settings_page_widget_pos.y += record_area_label->get_size().y + page_widget_spacing.y / 3;
auto record_area_box = std::make_unique<gsr::ComboBox>(&title_font);
record_area_box->set_position(settings_page_widget_pos);
// TODO: Show options not supported but disable them
if(gsr_info.supported_capture_options.window)
record_area_box->add_item("Window", "window");
if(gsr_info.supported_capture_options.focused)
record_area_box->add_item("Focused window", "focused");
if(gsr_info.supported_capture_options.screen)
record_area_box->add_item("All monitors", "screen");
for(const auto &monitor : gsr_info.supported_capture_options.monitors) {
char name[256];
snprintf(name, sizeof(name), "%s (%dx%d)", monitor.name.c_str(), monitor.size.x, monitor.size.y);
record_area_box->add_item(name, monitor.name);
}
if(gsr_info.supported_capture_options.portal)
record_area_box->add_item("Desktop portal", "portal");
settings_page_widget_pos.y += record_area_box->get_size().y + page_widget_spacing.y;
auto audio_device_box = std::make_unique<gsr::ComboBox>(&title_font);
audio_device_box->set_position(settings_page_widget_pos);
for(const auto &audio_device : audio_devices) {
audio_device_box->add_item(audio_device.description, audio_device.name);
}
settings_page_widget_pos.y += audio_device_box->get_size().y + page_widget_spacing.y;
auto framerate_label = std::make_unique<gsr::Label>(&title_font, "Frame rate:", gsr::get_theme().text_color);
framerate_label->set_position(settings_page_widget_pos);
settings_page_widget_pos.y += framerate_label->get_size().y + page_widget_spacing.y / 3;
auto framerate_box = std::make_unique<gsr::ComboBox>(&title_font);
framerate_box->set_position(settings_page_widget_pos);
framerate_box->add_item("60", "60");
framerate_box->add_item("30", "30");
settings_page_widget_pos.y += framerate_box->get_size().y + page_widget_spacing.y;
auto video_quality_label = std::make_unique<gsr::Label>(&title_font, "Video quality:", gsr::get_theme().text_color);
video_quality_label->set_position(settings_page_widget_pos);
const auto video_quality_label_pos = video_quality_label->get_position();
settings_page_widget_pos.y += video_quality_label->get_size().y + page_widget_spacing.y / 3;
auto video_quality_box = std::make_unique<gsr::ComboBox>(&title_font);
video_quality_box->set_position(settings_page_widget_pos);
video_quality_box->add_item("Medium", "medium");
video_quality_box->add_item("High (Recommended for live streaming)", "high");
video_quality_box->add_item("Very High (Recommended)", "very_high");
video_quality_box->add_item("Ultra", "ultra");
const auto video_quality_box_pos = video_quality_box->get_position();
const mgl::vec2f video_quality_box_size = video_quality_box->get_size();
settings_page_widget_pos.y += video_quality_box_size.y + page_widget_spacing.y;
auto color_range_label = std::make_unique<gsr::Label>(&title_font, "Color range:", gsr::get_theme().text_color);
color_range_label->set_position(video_quality_label_pos + mgl::vec2f(video_quality_box_size.x + page_widget_spacing.x, 0.0f).floor());
auto color_range_box = std::make_unique<gsr::ComboBox>(&title_font);
color_range_box->set_position(video_quality_box_pos + mgl::vec2f(video_quality_box_size.x + page_widget_spacing.x, 0.0f).floor());
color_range_box->add_item("Limited", "limited");
color_range_box->add_item("Full", "full");
auto video_codec_label = std::make_unique<gsr::Label>(&title_font, "Video codec:", gsr::get_theme().text_color);
video_codec_label->set_position(settings_page_widget_pos);
settings_page_widget_pos.y += video_codec_label->get_size().y + page_widget_spacing.y / 3;
auto video_codec_box = std::make_unique<gsr::ComboBox>(&title_font);
video_codec_box->set_position(settings_page_widget_pos);
// TODO: Show options not supported but disable them
video_codec_box->add_item("Auto (Recommended)", "auto");
if(gsr_info.supported_video_codecs.h264)
video_codec_box->add_item("H264", "h264");
if(gsr_info.supported_video_codecs.hevc)
video_codec_box->add_item("HEVC", "hevc");
if(gsr_info.supported_video_codecs.av1)
video_codec_box->add_item("AV1", "av1");
if(gsr_info.supported_video_codecs.vp8)
video_codec_box->add_item("VP8", "vp8");
if(gsr_info.supported_video_codecs.vp9)
video_codec_box->add_item("VP9", "vp9");
// TODO: Add hdr options
video_codec_box->add_item("H264 Software Encoder (Slow, not recommended)", "h264_software");
settings_page_widget_pos.y += video_codec_box->get_size().y + page_widget_spacing.y;
auto audio_codec_label = std::make_unique<gsr::Label>(&title_font, "Audio codec:", gsr::get_theme().text_color);
audio_codec_label->set_position(settings_page_widget_pos);
settings_page_widget_pos.y += audio_codec_label->get_size().y + page_widget_spacing.y / 3;
auto audio_codec_box = std::make_unique<gsr::ComboBox>(&title_font);
audio_codec_box->set_position(settings_page_widget_pos);
audio_codec_box->add_item("Opus (Recommended)", "opus");
audio_codec_box->add_item("AAC", "aac");
settings_page_widget_pos.y += audio_codec_box->get_size().y + page_widget_spacing.y;
auto framerate_mode_label = std::make_unique<gsr::Label>(&title_font, "Frame rate mode:", gsr::get_theme().text_color);
framerate_mode_label->set_position(settings_page_widget_pos);
settings_page_widget_pos.y += framerate_mode_label->get_size().y + page_widget_spacing.y / 3;
auto framerate_mode_box = std::make_unique<gsr::ComboBox>(&title_font);
framerate_mode_box->set_position(settings_page_widget_pos);
framerate_mode_box->add_item("Auto (Recommended)", "auto");
framerate_mode_box->add_item("Constant", "cfr");
framerate_mode_box->add_item("Variable", "vfr");
settings_page_widget_pos.y += framerate_mode_box->get_size().y + page_widget_spacing.y;
auto container_label = std::make_unique<gsr::Label>(&title_font, "Container:", gsr::get_theme().text_color);
container_label->set_position(settings_page_widget_pos);
settings_page_widget_pos.y += container_label->get_size().y + page_widget_spacing.y / 3;
auto container_box = std::make_unique<gsr::ComboBox>(&title_font);
container_box->set_position(settings_page_widget_pos);
container_box->add_item("mp4", "mp4");
container_box->add_item("mkv", "matroska");
container_box->add_item("flv", "flv");
container_box->add_item("mov", "mov");
container_box->add_item("ts", "mpegts");
container_box->add_item("m3u8", "hls");
settings_page_widget_pos.y += container_box->get_size().y + page_widget_spacing.y;
settings_content_page->add_widget(std::move(record_area_label));
settings_content_page->add_widget(std::move(record_area_box));
settings_content_page->add_widget(std::move(audio_device_box));
settings_content_page->add_widget(std::move(framerate_label));
settings_content_page->add_widget(std::move(framerate_box));
settings_content_page->add_widget(std::move(video_quality_label));
settings_content_page->add_widget(std::move(video_quality_box));
settings_content_page->add_widget(std::move(color_range_label));
settings_content_page->add_widget(std::move(color_range_box));
settings_content_page->add_widget(std::move(video_codec_label));
settings_content_page->add_widget(std::move(video_codec_box));
settings_content_page->add_widget(std::move(audio_codec_label));
settings_content_page->add_widget(std::move(audio_codec_box));
settings_content_page->add_widget(std::move(framerate_mode_label));
settings_content_page->add_widget(std::move(framerate_mode_box));
settings_content_page->add_widget(std::move(container_label));
settings_content_page->add_widget(std::move(container_box));
add_widgets_to_settings_page(title_font, window_size, settings_page_position, settings_page_size, settings_page, settings_content_page, gsr_info, audio_devices, settings_back_button_callback);
}
mgl::Texture close_texture;