diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/Button.cpp | 2 | ||||
-rw-r--r-- | src/gui/DropdownButton.cpp | 35 | ||||
-rw-r--r-- | src/gui/GlobalSettingsPage.cpp | 47 | ||||
-rw-r--r-- | src/gui/GsrPage.cpp | 5 | ||||
-rw-r--r-- | src/gui/List.cpp | 30 | ||||
-rw-r--r-- | src/gui/Page.cpp | 15 | ||||
-rw-r--r-- | src/gui/ScreenshotSettingsPage.cpp | 3 | ||||
-rw-r--r-- | src/gui/ScrollablePage.cpp | 13 | ||||
-rw-r--r-- | src/gui/SettingsPage.cpp | 384 | ||||
-rw-r--r-- | src/gui/StaticPage.cpp | 5 | ||||
-rw-r--r-- | src/gui/Subsection.cpp | 17 | ||||
-rw-r--r-- | src/gui/Widget.cpp | 16 |
12 files changed, 376 insertions, 196 deletions
diff --git a/src/gui/Button.cpp b/src/gui/Button.cpp index d8cb85b..6e343c4 100644 --- a/src/gui/Button.cpp +++ b/src/gui/Button.cpp @@ -63,7 +63,7 @@ namespace gsr { window.draw(sprite); const int padding_icon_right = padding_right_icon_scale * get_button_height(); - text.set_position((sprite.get_position() + mgl::vec2f(sprite.get_size().x + padding_icon_right, sprite.get_size().y * 0.5f - text.get_bounds().size.y * 0.5f)).floor()); + text.set_position((sprite.get_position() + mgl::vec2f(sprite.get_size().x + padding_icon_right, sprite.get_size().y * 0.5f - text.get_bounds().size.y * 0.52f)).floor()); window.draw(text); } else { text.set_position((draw_pos + item_size * 0.5f - text.get_bounds().size * 0.5f).floor()); diff --git a/src/gui/DropdownButton.cpp b/src/gui/DropdownButton.cpp index bdc4027..5d1cc38 100644 --- a/src/gui/DropdownButton.cpp +++ b/src/gui/DropdownButton.cpp @@ -110,6 +110,14 @@ namespace gsr { window.draw(rect); } + if(activated) { + description.set_color(get_color_theme().tint_color); + icon_sprite.set_color(get_color_theme().tint_color); + } else { + description.set_color(mgl::Color(150, 150, 150)); + icon_sprite.set_color(mgl::Color(255, 255, 255)); + } + const int text_margin = size.y * 0.085; const auto title_bounds = title.get_bounds(); @@ -148,7 +156,7 @@ namespace gsr { window.draw(separator); } - if(mouse_inside_item == -1) { + if(mouse_inside_item == -1 && item.enabled) { 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, get_color_theme().tint_color, border_size); @@ -161,16 +169,18 @@ namespace gsr { mgl::Sprite icon(item.icon_texture); icon.set_height((int)(item_size.y * 0.4f)); icon.set_position((item_position + mgl::vec2f(padding_left, item_size.y * 0.5f - icon.get_size().y * 0.5f)).floor()); + icon.set_color(item.enabled ? mgl::Color(255, 255, 255, 255) : mgl::Color(255, 255, 255, 80)); window.draw(icon); icon_offset = icon.get_size().x + icon_spacing; } item.text.set_position((item_position + mgl::vec2f(padding_left + icon_offset, item_size.y * 0.5f - text_bounds.size.y * 0.5f)).floor()); + item.text.set_color(item.enabled ? mgl::Color(255, 255, 255, 255) : mgl::Color(255, 255, 255, 80)); window.draw(item.text); const auto description_bounds = item.description_text.get_bounds(); item.description_text.set_position((item_position + mgl::vec2f(item_size.x - description_bounds.size.x - padding_right, item_size.y * 0.5f - description_bounds.size.y * 0.5f)).floor()); - item.description_text.set_color(mgl::Color(255, 255, 255, 120)); + item.description_text.set_color(item.enabled ? mgl::Color(255, 255, 255, 120) : mgl::Color(255, 255, 255, 40)); window.draw(item.description_text); item_position.y += item_size.y; @@ -179,6 +189,10 @@ namespace gsr { } void DropdownButton::add_item(const std::string &text, const std::string &id, const std::string &description) { + for(auto &item : items) { + if(item.id == id) + return; + } items.push_back({mgl::Text(text, *title_font), mgl::Text(description, *description_font), nullptr, id}); dirty = true; } @@ -210,6 +224,15 @@ namespace gsr { } } + void DropdownButton::set_item_enabled(const std::string &id, bool enabled) { + for(auto &item : items) { + if(item.id == id) { + item.enabled = enabled; + return; + } + } + } + void DropdownButton::set_description(std::string description_text) { description.set_string(std::move(description_text)); } @@ -219,14 +242,6 @@ namespace gsr { return; this->activated = activated; - - if(activated) { - description.set_color(get_color_theme().tint_color); - icon_sprite.set_color(get_color_theme().tint_color); - } else { - description.set_color(mgl::Color(150, 150, 150)); - icon_sprite.set_color(mgl::Color(255, 255, 255)); - } } void DropdownButton::update_if_dirty() { diff --git a/src/gui/GlobalSettingsPage.cpp b/src/gui/GlobalSettingsPage.cpp index 1e2a444..ccebb92 100644 --- a/src/gui/GlobalSettingsPage.cpp +++ b/src/gui/GlobalSettingsPage.cpp @@ -149,7 +149,7 @@ namespace gsr { tint_color_radio_button_ptr = tint_color_radio_button.get(); tint_color_radio_button->add_item("Red", "amd"); tint_color_radio_button->add_item("Green", "nvidia"); - tint_color_radio_button->add_item("blue", "intel"); + tint_color_radio_button->add_item("Blue", "intel"); tint_color_radio_button->on_selection_changed = [](const std::string&, const std::string &id) { if(id == "amd") get_color_theme().tint_color = mgl::Color(221, 0, 49); @@ -256,6 +256,30 @@ namespace gsr { return list; } + std::unique_ptr<List> GlobalSettingsPage::create_replay_partial_save_hotkey_options() { + auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER); + + list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Save 1 minute replay:", get_color_theme().text_color)); + auto save_replay_1_min_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120)); + save_replay_1_min_button_ptr = save_replay_1_min_button.get(); + list->add_widget(std::move(save_replay_1_min_button)); + + list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Save 10 minute replay:", get_color_theme().text_color)); + auto save_replay_10_min_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120)); + save_replay_10_min_button_ptr = save_replay_10_min_button.get(); + list->add_widget(std::move(save_replay_10_min_button)); + + save_replay_1_min_button_ptr->on_click = [this] { + configure_hotkey_start(ConfigureHotkeyType::REPLAY_SAVE_1_MIN); + }; + + save_replay_10_min_button_ptr->on_click = [this] { + configure_hotkey_start(ConfigureHotkeyType::REPLAY_SAVE_10_MIN); + }; + + return list; + } + std::unique_ptr<List> GlobalSettingsPage::create_record_hotkey_options() { auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER); @@ -335,6 +359,8 @@ namespace gsr { config.record_config.pause_unpause_hotkey = {mgl::Keyboard::Unknown, 0}; config.replay_config.start_stop_hotkey = {mgl::Keyboard::Unknown, 0}; config.replay_config.save_hotkey = {mgl::Keyboard::Unknown, 0}; + config.replay_config.save_1_min_hotkey = {mgl::Keyboard::Unknown, 0}; + config.replay_config.save_10_min_hotkey = {mgl::Keyboard::Unknown, 0}; config.screenshot_config.take_screenshot_hotkey = {mgl::Keyboard::Unknown, 0}; config.screenshot_config.take_screenshot_region_hotkey = {mgl::Keyboard::Unknown, 0}; config.main_config.show_hide_hotkey = {mgl::Keyboard::Unknown, 0}; @@ -374,6 +400,7 @@ namespace gsr { list_ptr->add_widget(std::make_unique<LineSeparator>(LineSeparator::Orientation::HORIZONTAL, subsection->get_inner_size().x)); list_ptr->add_widget(create_show_hide_hotkey_options()); list_ptr->add_widget(create_replay_hotkey_options()); + list_ptr->add_widget(create_replay_partial_save_hotkey_options()); list_ptr->add_widget(create_record_hotkey_options()); list_ptr->add_widget(create_stream_hotkey_options()); list_ptr->add_widget(create_screenshot_hotkey_options()); @@ -393,6 +420,8 @@ namespace gsr { list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_options_texture, get_theme().body_font.get_character_size(), "to show/hide the UI")); list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_dpad_up_texture, get_theme().body_font.get_character_size(), "to take a screenshot")); list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_dpad_down_texture, get_theme().body_font.get_character_size(), "to save a replay")); + list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_cross_texture, get_theme().body_font.get_character_size(), "to save a 1 minute replay")); + list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_triangle_texture, get_theme().body_font.get_character_size(), "to save a 10 minute replay")); list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_dpad_left_texture, get_theme().body_font.get_character_size(), "to start/stop recording")); list_ptr->add_widget(create_joystick_hotkey_text(&get_theme().ps4_home_texture, &get_theme().ps4_dpad_right_texture, get_theme().body_font.get_character_size(), "to turn replay on/off")); return subsection; @@ -490,6 +519,8 @@ namespace gsr { void GlobalSettingsPage::load_hotkeys() { turn_replay_on_off_button_ptr->set_text(config.replay_config.start_stop_hotkey.to_string()); save_replay_button_ptr->set_text(config.replay_config.save_hotkey.to_string()); + save_replay_1_min_button_ptr->set_text(config.replay_config.save_1_min_hotkey.to_string()); + save_replay_10_min_button_ptr->set_text(config.replay_config.save_10_min_hotkey.to_string()); start_stop_recording_button_ptr->set_text(config.record_config.start_stop_hotkey.to_string()); pause_unpause_recording_button_ptr->set_text(config.record_config.pause_unpause_hotkey.to_string()); @@ -567,6 +598,10 @@ namespace gsr { return turn_replay_on_off_button_ptr; case ConfigureHotkeyType::REPLAY_SAVE: return save_replay_button_ptr; + case ConfigureHotkeyType::REPLAY_SAVE_1_MIN: + return save_replay_1_min_button_ptr; + case ConfigureHotkeyType::REPLAY_SAVE_10_MIN: + return save_replay_10_min_button_ptr; case ConfigureHotkeyType::RECORD_START_STOP: return start_stop_recording_button_ptr; case ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE: @@ -591,6 +626,10 @@ namespace gsr { return &config.replay_config.start_stop_hotkey; case ConfigureHotkeyType::REPLAY_SAVE: return &config.replay_config.save_hotkey; + case ConfigureHotkeyType::REPLAY_SAVE_1_MIN: + return &config.replay_config.save_1_min_hotkey; + case ConfigureHotkeyType::REPLAY_SAVE_10_MIN: + return &config.replay_config.save_10_min_hotkey; case ConfigureHotkeyType::RECORD_START_STOP: return &config.record_config.start_stop_hotkey; case ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE: @@ -643,6 +682,12 @@ namespace gsr { case ConfigureHotkeyType::REPLAY_SAVE: hotkey_configure_action_name = "Save replay"; break; + case ConfigureHotkeyType::REPLAY_SAVE_1_MIN: + hotkey_configure_action_name = "Save 1 minute replay"; + break; + case ConfigureHotkeyType::REPLAY_SAVE_10_MIN: + hotkey_configure_action_name = "Save 10 minute replay"; + break; case ConfigureHotkeyType::RECORD_START_STOP: hotkey_configure_action_name = "Start/stop recording"; break; diff --git a/src/gui/GsrPage.cpp b/src/gui/GsrPage.cpp index 663187c..b4005f5 100644 --- a/src/gui/GsrPage.cpp +++ b/src/gui/GsrPage.cpp @@ -39,8 +39,9 @@ namespace gsr { // Process widgets by visibility (backwards) return widgets.for_each_reverse([selected_widget, &window, &event, content_page_position](std::unique_ptr<Widget> &widget) { - if(widget.get() != selected_widget) { - if(!widget->on_event(event, window, content_page_position)) + Widget *p = widget.get(); + if(p != selected_widget) { + if(!p->on_event(event, window, content_page_position)) return false; } return true; diff --git a/src/gui/List.cpp b/src/gui/List.cpp index 5294e36..57a6045 100644 --- a/src/gui/List.cpp +++ b/src/gui/List.cpp @@ -24,14 +24,23 @@ namespace gsr { // Process widgets by visibility (backwards) return widgets.for_each_reverse([selected_widget, &event, &window](std::unique_ptr<Widget> &widget) { // Ignore offset because widgets are positioned with offset in ::draw, this solution is simpler - if(widget.get() != selected_widget) { - if(!widget->on_event(event, window, mgl::vec2f(0.0f, 0.0f))) + Widget *p = widget.get(); + if(p != selected_widget) { + if(!p->on_event(event, window, mgl::vec2f(0.0f, 0.0f))) return false; } return true; }); } + List::~List() { + widgets.for_each([this](std::unique_ptr<Widget> &widget) { + if(widget->parent_widget == this) + widget->parent_widget = nullptr; + return true; + }, true); + } + void List::draw(mgl::Window &window, mgl::vec2f offset) { if(!visible) return; @@ -104,15 +113,6 @@ namespace gsr { selected_widget->draw(window, mgl::vec2f(0.0f, 0.0f)); } - // void List::remove_child_widget(Widget *widget) { - // for(auto it = widgets.begin(), end = widgets.end(); it != end; ++it) { - // if(it->get() == widget) { - // widgets.erase(it); - // return; - // } - // } - // } - void List::add_widget(std::unique_ptr<Widget> widget) { widget->parent_widget = this; widgets.push_back(std::move(widget)); @@ -122,6 +122,10 @@ namespace gsr { widgets.remove(widget); } + void List::replace_widget(Widget *widget, std::unique_ptr<Widget> new_widget) { + widgets.replace_item(widget, std::move(new_widget)); + } + void List::clear() { widgets.clear(); } @@ -137,6 +141,10 @@ namespace gsr { return nullptr; } + size_t List::get_num_children() const { + return widgets.size(); + } + void List::set_spacing(float spacing) { spacing_scale = spacing; } diff --git a/src/gui/Page.cpp b/src/gui/Page.cpp index ae13d82..5f21b71 100644 --- a/src/gui/Page.cpp +++ b/src/gui/Page.cpp @@ -1,14 +1,13 @@ #include "../../include/gui/Page.hpp" namespace gsr { - // void Page::remove_child_widget(Widget *widget) { - // for(auto it = widgets.begin(), end = widgets.end(); it != end; ++it) { - // if(it->get() == widget) { - // widgets.erase(it); - // return; - // } - // } - // } + Page::~Page() { + widgets.for_each([this](std::unique_ptr<Widget> &widget) { + if(widget->parent_widget == this) + widget->parent_widget = nullptr; + return true; + }, true); + } void Page::add_widget(std::unique_ptr<Widget> widget) { widget->parent_widget = this; diff --git a/src/gui/ScreenshotSettingsPage.cpp b/src/gui/ScreenshotSettingsPage.cpp index 2dedd86..5b8efbd 100644 --- a/src/gui/ScreenshotSettingsPage.cpp +++ b/src/gui/ScreenshotSettingsPage.cpp @@ -257,8 +257,7 @@ namespace gsr { void ScreenshotSettingsPage::add_widgets() { content_page_ptr->add_widget(create_settings()); - record_area_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) { - (void)text; + record_area_box_ptr->on_selection_changed = [this](const std::string&, const std::string &id) { const bool window_selected = id == "window"; const bool portal_selected = id == "portal"; select_window_list_ptr->set_visible(window_selected); diff --git a/src/gui/ScrollablePage.cpp b/src/gui/ScrollablePage.cpp index d5e92d0..cec20d3 100644 --- a/src/gui/ScrollablePage.cpp +++ b/src/gui/ScrollablePage.cpp @@ -15,6 +15,14 @@ namespace gsr { ScrollablePage::ScrollablePage(mgl::vec2f size) : size(size) {} + ScrollablePage::~ScrollablePage() { + widgets.for_each([this](std::unique_ptr<Widget> &widget) { + if(widget->parent_widget == this) + widget->parent_widget = nullptr; + return true; + }, true); + } + bool ScrollablePage::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) { if(!visible) return true; @@ -57,8 +65,9 @@ namespace gsr { // Process widgets by visibility (backwards) const bool continue_events = widgets.for_each_reverse([selected_widget, &window, &event, offset](std::unique_ptr<Widget> &widget) { - if(widget.get() != selected_widget) { - if(!widget->on_event(event, window, offset)) + Widget *p = widget.get(); + if(p != selected_widget) { + if(!p->on_event(event, window, offset)) return false; } return true; diff --git a/src/gui/SettingsPage.cpp b/src/gui/SettingsPage.cpp index 663e941..9890d17 100644 --- a/src/gui/SettingsPage.cpp +++ b/src/gui/SettingsPage.cpp @@ -11,6 +11,8 @@ #include <string.h> namespace gsr { + static const char *custom_app_audio_tag = "[custom]"; + enum class AudioTrackType { DEVICE, APPLICATION, @@ -202,121 +204,201 @@ namespace gsr { return audio_device_box; } - std::unique_ptr<Button> SettingsPage::create_remove_audio_device_button(List *audio_device_list_ptr) { - auto remove_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "Remove", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120)); - remove_audio_track_button->on_click = [this, audio_device_list_ptr]() { - audio_track_list_ptr->remove_widget(audio_device_list_ptr); + static void set_application_audio_options_visible(Subsection *audio_track_subsection, bool visible, const GsrInfo &gsr_info) { + if(!gsr_info.system_info.supports_app_audio) + visible = false; + + List *audio_track_items_list = dynamic_cast<List*>(audio_track_subsection->get_inner_widget()); + + List *buttons_list = dynamic_cast<List*>(audio_track_items_list->get_child_widget_by_index(1)); + Button *add_application_audio_button = dynamic_cast<Button*>(buttons_list->get_child_widget_by_index(1)); + add_application_audio_button->set_visible(visible); + + CheckBox *invert_app_audio_checkbox = dynamic_cast<CheckBox*>(audio_track_items_list->get_child_widget_by_index(3)); + invert_app_audio_checkbox->set_visible(visible); + } + + static void set_application_audio_options_visible(List *audio_track_section_list_ptr, bool visible, const GsrInfo &gsr_info) { + audio_track_section_list_ptr->for_each_child_widget([visible, &gsr_info](std::unique_ptr<Widget> &widget) { + Subsection *audio_track_subsection = dynamic_cast<Subsection*>(widget.get()); + set_application_audio_options_visible(audio_track_subsection, visible, gsr_info); + return true; + }); + } + + std::unique_ptr<Button> SettingsPage::create_remove_audio_device_button(List *audio_input_list_ptr, List *audio_device_list_ptr) { + auto remove_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 0)); + remove_audio_track_button->set_icon(&get_theme().trash_texture); + remove_audio_track_button->set_icon_padding_scale(0.75f); + remove_audio_track_button->on_click = [audio_input_list_ptr, audio_device_list_ptr]() { + audio_input_list_ptr->remove_widget(audio_device_list_ptr); }; return remove_audio_track_button; } - std::unique_ptr<List> SettingsPage::create_audio_device() { + std::unique_ptr<List> SettingsPage::create_audio_device(List *audio_input_list_ptr) { auto audio_device_list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER); audio_device_list->userdata = (void*)(uintptr_t)AudioTrackType::DEVICE; audio_device_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Device:", get_color_theme().text_color)); audio_device_list->add_widget(create_audio_device_selection_combobox()); - audio_device_list->add_widget(create_remove_audio_device_button(audio_device_list.get())); + audio_device_list->add_widget(create_remove_audio_device_button(audio_input_list_ptr, audio_device_list.get())); return audio_device_list; } - std::unique_ptr<Button> SettingsPage::create_add_audio_device_button() { + std::unique_ptr<Button> SettingsPage::create_add_audio_track_button() { + auto button = std::make_unique<Button>(&get_theme().body_font, "Add audio track", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120)); + button->on_click = [this]() { + audio_track_section_list_ptr->add_widget(create_audio_track_section(audio_section_ptr)); + }; + button->set_visible(type != Type::STREAM); + return button; + } + + std::unique_ptr<Button> SettingsPage::create_add_audio_device_button(List *audio_input_list_ptr) { auto add_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "Add audio device", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120)); - add_audio_track_button->on_click = [this]() { + add_audio_track_button->on_click = [this, audio_input_list_ptr]() { audio_devices = get_audio_devices(); - audio_track_list_ptr->add_widget(create_audio_device()); + audio_input_list_ptr->add_widget(create_audio_device(audio_input_list_ptr)); }; return add_audio_track_button; } - std::unique_ptr<ComboBox> SettingsPage::create_application_audio_selection_combobox() { + std::unique_ptr<ComboBox> SettingsPage::create_application_audio_selection_combobox(List *application_audio_row) { auto audio_device_box = std::make_unique<ComboBox>(&get_theme().body_font); + ComboBox *audio_device_box_ptr = audio_device_box.get(); for(const auto &app_audio : application_audio) { audio_device_box->add_item(app_audio, app_audio); } + audio_device_box->add_item("Custom...", custom_app_audio_tag); + + audio_device_box->on_selection_changed = [application_audio_row, audio_device_box_ptr](const std::string&, const std::string &id) { + if(id == custom_app_audio_tag) { + application_audio_row->userdata = (void*)(uintptr_t)AudioTrackType::APPLICATION_CUSTOM; + auto custom_app_audio_entry = std::make_unique<Entry>(&get_theme().body_font, "", (int)(get_theme().body_font.get_character_size() * 10.0f)); + application_audio_row->replace_widget(audio_device_box_ptr, std::move(custom_app_audio_entry)); + } + }; + return audio_device_box; } - std::unique_ptr<List> SettingsPage::create_application_audio() { + std::unique_ptr<List> SettingsPage::create_application_audio(List *audio_input_list_ptr) { auto application_audio_list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER); application_audio_list->userdata = (void*)(uintptr_t)AudioTrackType::APPLICATION; application_audio_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "App: ", get_color_theme().text_color)); - application_audio_list->add_widget(create_application_audio_selection_combobox()); - application_audio_list->add_widget(create_remove_audio_device_button(application_audio_list.get())); + application_audio_list->add_widget(create_application_audio_selection_combobox(application_audio_list.get())); + application_audio_list->add_widget(create_remove_audio_device_button(audio_input_list_ptr, application_audio_list.get())); return application_audio_list; } - std::unique_ptr<List> SettingsPage::create_custom_application_audio() { + std::unique_ptr<List> SettingsPage::create_custom_application_audio(List *audio_input_list_ptr) { auto application_audio_list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER); application_audio_list->userdata = (void*)(uintptr_t)AudioTrackType::APPLICATION_CUSTOM; application_audio_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "App: ", get_color_theme().text_color)); application_audio_list->add_widget(std::make_unique<Entry>(&get_theme().body_font, "", (int)(get_theme().body_font.get_character_size() * 10.0f))); - application_audio_list->add_widget(create_remove_audio_device_button(application_audio_list.get())); + application_audio_list->add_widget(create_remove_audio_device_button(audio_input_list_ptr, application_audio_list.get())); return application_audio_list; } - std::unique_ptr<Button> SettingsPage::create_add_application_audio_button() { + std::unique_ptr<Button> SettingsPage::create_add_application_audio_button(List *audio_input_list_ptr) { auto add_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "Add application audio", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120)); - add_application_audio_button_ptr = add_audio_track_button.get(); - add_audio_track_button->on_click = [this]() { + add_audio_track_button->on_click = [this, audio_input_list_ptr]() { application_audio = get_application_audio(); - audio_track_list_ptr->add_widget(create_application_audio()); - }; - return add_audio_track_button; - } - - std::unique_ptr<Button> SettingsPage::create_add_custom_application_audio_button() { - auto add_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "Add custom application audio", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120)); - add_custom_application_audio_button_ptr = add_audio_track_button.get(); - add_audio_track_button->on_click = [this]() { - audio_track_list_ptr->add_widget(create_custom_application_audio()); + if(application_audio.empty()) + audio_input_list_ptr->add_widget(create_custom_application_audio(audio_input_list_ptr)); + else + audio_input_list_ptr->add_widget(create_application_audio(audio_input_list_ptr)); }; return add_audio_track_button; } - std::unique_ptr<List> SettingsPage::create_add_audio_buttons() { + std::unique_ptr<List> SettingsPage::create_add_audio_buttons(List *audio_input_list_ptr) { auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER); - list->add_widget(create_add_audio_device_button()); - list->add_widget(create_add_application_audio_button()); - list->add_widget(create_add_custom_application_audio_button()); + list->add_widget(create_add_audio_device_button(audio_input_list_ptr)); + list->add_widget(create_add_application_audio_button(audio_input_list_ptr)); return list; } - std::unique_ptr<List> SettingsPage::create_audio_track_track_section() { + std::unique_ptr<List> SettingsPage::create_audio_input_section() { auto list = std::make_unique<List>(List::Orientation::VERTICAL); - audio_track_list_ptr = list.get(); - audio_track_list_ptr->add_widget(create_audio_device()); // Add default_output by default + //list->add_widget(create_audio_device(list.get())); // Add default_output by default return list; } - std::unique_ptr<CheckBox> SettingsPage::create_split_audio_checkbox() { - auto split_audio_checkbox = std::make_unique<CheckBox>(&get_theme().body_font, "Split each device/app audio into separate audio tracks"); - split_audio_checkbox->set_checked(false); - split_audio_checkbox_ptr = split_audio_checkbox.get(); - return split_audio_checkbox; - } - std::unique_ptr<CheckBox> SettingsPage::create_application_audio_invert_checkbox() { auto application_audio_invert_checkbox = std::make_unique<CheckBox>(&get_theme().body_font, "Record audio from all applications except the selected ones"); application_audio_invert_checkbox->set_checked(false); - application_audio_invert_checkbox_ptr = application_audio_invert_checkbox.get(); return application_audio_invert_checkbox; } - std::unique_ptr<Widget> SettingsPage::create_audio_track_section() { + static void update_audio_track_titles(List *audio_track_section_list_ptr) { + int index = 0; + audio_track_section_list_ptr->for_each_child_widget([&index](std::unique_ptr<Widget> &widget) { + char audio_track_name[32]; + snprintf(audio_track_name, sizeof(audio_track_name), "Audio track #%d", 1 + index); + ++index; + + Subsection *subsection = dynamic_cast<Subsection*>(widget.get()); + List *subesection_items = dynamic_cast<List*>(subsection->get_inner_widget()); + Label *audio_track_title = dynamic_cast<Label*>(dynamic_cast<List*>(subesection_items->get_child_widget_by_index(0))->get_child_widget_by_index(0)); + audio_track_title->set_text(audio_track_name); + return true; + }); + } + + std::unique_ptr<List> SettingsPage::create_audio_track_title_and_remove(Subsection *audio_track_subsection, const char *title) { + auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER); + list->add_widget(std::make_unique<Label>(&get_theme().title_font, title, get_color_theme().text_color)); + + auto remove_track_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 0)); + remove_track_button->set_icon(&get_theme().trash_texture); + remove_track_button->set_icon_padding_scale(0.75f); + remove_track_button->on_click = [this, audio_track_subsection]() { + audio_track_section_list_ptr->remove_widget(audio_track_subsection); + update_audio_track_titles(audio_track_section_list_ptr); + }; + list->add_widget(std::move(remove_track_button)); + list->set_visible(type != Type::STREAM); + return list; + } + + std::unique_ptr<Subsection> SettingsPage::create_audio_track_section(Widget *parent_widget) { + char audio_track_name[32]; + snprintf(audio_track_name, sizeof(audio_track_name), "Audio track #%d", 1 + (int)audio_track_section_list_ptr->get_num_children()); + + auto audio_input_section = create_audio_input_section(); + List *audio_input_section_ptr = audio_input_section.get(); + auto list = std::make_unique<List>(List::Orientation::VERTICAL); - list->add_widget(create_add_audio_buttons()); - list->add_widget(create_audio_track_track_section()); + List *list_ptr = list.get(); + auto subsection = std::make_unique<Subsection>("", std::move(std::move(list)), mgl::vec2f(parent_widget->get_inner_size().x, 0.0f)); + subsection->set_bg_color(mgl::Color(35, 40, 44)); + + list_ptr->add_widget(create_audio_track_title_and_remove(subsection.get(), audio_track_name)); + list_ptr->add_widget(create_add_audio_buttons(audio_input_section_ptr)); + list_ptr->add_widget(std::move(audio_input_section)); + list_ptr->add_widget(create_application_audio_invert_checkbox()); + + set_application_audio_options_visible(subsection.get(), view_radio_button_ptr->get_selected_id() == "advanced", *gsr_info); + return subsection; + } + + std::unique_ptr<List> SettingsPage::create_audio_track_section_list() { + auto list = std::make_unique<List>(List::Orientation::VERTICAL); + audio_track_section_list_ptr = list.get(); return list; } std::unique_ptr<Widget> SettingsPage::create_audio_section() { auto audio_device_section_list = std::make_unique<List>(List::Orientation::VERTICAL); - audio_device_section_list->add_widget(create_audio_track_section()); - if(type != Type::STREAM) - audio_device_section_list->add_widget(create_split_audio_checkbox()); - audio_device_section_list->add_widget(create_application_audio_invert_checkbox()); - audio_device_section_list->add_widget(create_audio_codec()); - return std::make_unique<Subsection>("Audio", std::move(audio_device_section_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)); + List *audio_device_section_list_ptr = audio_device_section_list.get(); + + auto subsection = std::make_unique<Subsection>("Audio", std::move(audio_device_section_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)); + audio_section_ptr = subsection.get(); + audio_device_section_list_ptr->add_widget(create_add_audio_track_button()); + audio_device_section_list_ptr->add_widget(create_audio_track_section_list()); + audio_device_section_list_ptr->add_widget(create_audio_codec()); + return subsection; } std::unique_ptr<List> SettingsPage::create_video_quality_box() { @@ -531,8 +613,7 @@ namespace gsr { void SettingsPage::add_widgets() { content_page_ptr->add_widget(create_settings()); - record_area_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) { - (void)text; + record_area_box_ptr->on_selection_changed = [this](const std::string&, const std::string &id) { const bool window_selected = id == "window"; const bool focused_selected = id == "focused"; const bool portal_selected = id == "portal"; @@ -549,8 +630,7 @@ namespace gsr { video_resolution_list_ptr->set_visible(!focused_selected && checked); }; - video_quality_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) { - (void)text; + video_quality_box_ptr->on_selection_changed = [this](const std::string&, const std::string &id) { const bool custom_selected = id == "custom"; video_bitrate_list_ptr->set_visible(custom_selected); @@ -569,12 +649,6 @@ namespace gsr { record_area_box_ptr->set_selected_item("window"); else record_area_box_ptr->on_selection_changed("", ""); - - if(!gsr_info->system_info.supports_app_audio) { - add_application_audio_button_ptr->set_visible(false); - add_custom_application_audio_button_ptr->set_visible(false); - application_audio_invert_checkbox_ptr->set_visible(false); - } } void SettingsPage::add_page_specific_widgets() { @@ -716,6 +790,16 @@ namespace gsr { replay_time_label_ptr->set_text(buffer); } + void SettingsPage::view_changed(bool advanced_view, Subsection *notifications_subsection_ptr) { + color_range_list_ptr->set_visible(advanced_view); + audio_codec_ptr->set_visible(advanced_view); + video_codec_ptr->set_visible(advanced_view); + framerate_mode_list_ptr->set_visible(advanced_view); + notifications_subsection_ptr->set_visible(advanced_view); + set_application_audio_options_visible(audio_track_section_list_ptr, advanced_view, *gsr_info); + settings_scrollable_page_ptr->reset_scroll(); + } + void SettingsPage::add_replay_widgets() { auto file_info_list = std::make_unique<List>(List::Orientation::VERTICAL); auto file_info_data_list = std::make_unique<List>(List::Orientation::HORIZONTAL); @@ -754,16 +838,8 @@ namespace gsr { Subsection *notifications_subsection_ptr = notifications_subsection.get(); settings_list_ptr->add_widget(std::move(notifications_subsection)); - view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string &text, const std::string &id) { - (void)text; - const bool advanced_view = id == "advanced"; - color_range_list_ptr->set_visible(advanced_view); - audio_codec_ptr->set_visible(advanced_view); - video_codec_ptr->set_visible(advanced_view); - framerate_mode_list_ptr->set_visible(advanced_view); - notifications_subsection_ptr->set_visible(advanced_view); - split_audio_checkbox_ptr->set_visible(advanced_view); - settings_scrollable_page_ptr->reset_scroll(); + view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string&, const std::string &id) { + view_changed(id == "advanced", notifications_subsection_ptr); return true; }; view_radio_button_ptr->on_selection_changed("Simple", "simple"); @@ -828,16 +904,8 @@ namespace gsr { Subsection *notifications_subsection_ptr = notifications_subsection.get(); settings_list_ptr->add_widget(std::move(notifications_subsection)); - view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string &text, const std::string &id) { - (void)text; - const bool advanced_view = id == "advanced"; - color_range_list_ptr->set_visible(advanced_view); - audio_codec_ptr->set_visible(advanced_view); - video_codec_ptr->set_visible(advanced_view); - framerate_mode_list_ptr->set_visible(advanced_view); - notifications_subsection_ptr->set_visible(advanced_view); - split_audio_checkbox_ptr->set_visible(advanced_view); - settings_scrollable_page_ptr->reset_scroll(); + view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string&, const std::string &id) { + view_changed(id == "advanced", notifications_subsection_ptr); return true; }; view_radio_button_ptr->on_selection_changed("Simple", "simple"); @@ -933,8 +1001,7 @@ namespace gsr { Subsection *notifications_subsection_ptr = notifications_subsection.get(); settings_list_ptr->add_widget(std::move(notifications_subsection)); - streaming_service_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) { - (void)text; + streaming_service_box_ptr->on_selection_changed = [this](const std::string&, const std::string &id) { const bool twitch_option = id == "twitch"; const bool youtube_option = id == "youtube"; const bool custom_option = id == "custom"; @@ -947,15 +1014,8 @@ namespace gsr { }; streaming_service_box_ptr->on_selection_changed("Twitch", "twitch"); - view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string &text, const std::string &id) { - (void)text; - const bool advanced_view = id == "advanced"; - color_range_list_ptr->set_visible(advanced_view); - audio_codec_ptr->set_visible(advanced_view); - video_codec_ptr->set_visible(advanced_view); - framerate_mode_list_ptr->set_visible(advanced_view); - notifications_subsection_ptr->set_visible(advanced_view); - settings_scrollable_page_ptr->reset_scroll(); + view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string&, const std::string &id) { + view_changed(id == "advanced", notifications_subsection_ptr); return true; }; view_radio_button_ptr->on_selection_changed("Simple", "simple"); @@ -1006,50 +1066,61 @@ namespace gsr { return nullptr; } - static bool starts_with(std::string_view str, const char *substr) { - size_t len = strlen(substr); - return str.size() >= len && memcmp(str.data(), substr, len) == 0; - } - void SettingsPage::load_audio_tracks(const RecordOptions &record_options) { - audio_track_list_ptr->clear(); - for(const std::string &audio_track : record_options.audio_tracks) { - if(starts_with(audio_track, "app:")) { - if(!gsr_info->system_info.supports_app_audio) - continue; - - std::string audio_track_name = audio_track.substr(4); - const std::string *app_audio = get_application_audio_by_name_case_insensitive(application_audio, audio_track_name); - if(app_audio) { - std::unique_ptr<List> application_audio_widget = create_application_audio(); - ComboBox *application_audio_box = static_cast<ComboBox*>(application_audio_widget->get_child_widget_by_index(1)); - application_audio_box->set_selected_item(*app_audio); - audio_track_list_ptr->add_widget(std::move(application_audio_widget)); + audio_track_section_list_ptr->clear(); + for(const AudioTrack &audio_track : record_options.audio_tracks_list) { + auto audio_track_section = create_audio_track_section(audio_section_ptr); + List *audio_track_section_items_list_ptr = dynamic_cast<List*>(audio_track_section->get_inner_widget()); + List *audio_input_list_ptr = dynamic_cast<List*>(audio_track_section_items_list_ptr->get_child_widget_by_index(2)); + CheckBox *application_audio_invert_checkbox_ptr = dynamic_cast<CheckBox*>(audio_track_section_items_list_ptr->get_child_widget_by_index(3)); + application_audio_invert_checkbox_ptr->set_checked(audio_track.application_audio_invert); + + audio_input_list_ptr->clear(); + for(const std::string &audio_input : audio_track.audio_inputs) { + if(starts_with(audio_input, "app:")) { + if(!gsr_info->system_info.supports_app_audio) + continue; + + std::string audio_track_name = audio_input.substr(4); + const std::string *app_audio = get_application_audio_by_name_case_insensitive(application_audio, audio_track_name); + if(app_audio) { + std::unique_ptr<List> application_audio_widget = create_application_audio(audio_input_list_ptr); + ComboBox *application_audio_box = dynamic_cast<ComboBox*>(application_audio_widget->get_child_widget_by_index(1)); + application_audio_box->set_selected_item(*app_audio); + audio_input_list_ptr->add_widget(std::move(application_audio_widget)); + } else { + std::unique_ptr<List> application_audio_widget = create_custom_application_audio(audio_input_list_ptr); + Entry *application_audio_entry = dynamic_cast<Entry*>(application_audio_widget->get_child_widget_by_index(1)); + application_audio_entry->set_text(std::move(audio_track_name)); + audio_input_list_ptr->add_widget(std::move(application_audio_widget)); + } + } else if(starts_with(audio_input, "device:")) { + std::unique_ptr<List> audio_track_widget = create_audio_device(audio_input_list_ptr); + ComboBox *audio_device_box = dynamic_cast<ComboBox*>(audio_track_widget->get_child_widget_by_index(1)); + audio_device_box->set_selected_item(audio_input.substr(7)); + audio_input_list_ptr->add_widget(std::move(audio_track_widget)); } else { - std::unique_ptr<List> application_audio_widget = create_custom_application_audio(); - Entry *application_audio_entry = static_cast<Entry*>(application_audio_widget->get_child_widget_by_index(1)); - application_audio_entry->set_text(std::move(audio_track_name)); - audio_track_list_ptr->add_widget(std::move(application_audio_widget)); + std::unique_ptr<List> audio_track_widget = create_audio_device(audio_input_list_ptr); + ComboBox *audio_device_box = dynamic_cast<ComboBox*>(audio_track_widget->get_child_widget_by_index(1)); + audio_device_box->set_selected_item(audio_input); + audio_input_list_ptr->add_widget(std::move(audio_track_widget)); } - } else if(starts_with(audio_track, "device:")) { - std::unique_ptr<List> audio_track_widget = create_audio_device(); - ComboBox *audio_device_box = static_cast<ComboBox*>(audio_track_widget->get_child_widget_by_index(1)); - audio_device_box->set_selected_item(audio_track.substr(7)); - audio_track_list_ptr->add_widget(std::move(audio_track_widget)); - } else { - std::unique_ptr<List> audio_track_widget = create_audio_device(); - ComboBox *audio_device_box = static_cast<ComboBox*>(audio_track_widget->get_child_widget_by_index(1)); - audio_device_box->set_selected_item(audio_track); - audio_track_list_ptr->add_widget(std::move(audio_track_widget)); } + + audio_track_section_list_ptr->add_widget(std::move(audio_track_section)); + + if(type == Type::STREAM) + break; + } + + if(type == Type::STREAM && audio_track_section_list_ptr->get_num_children() == 0) { + auto audio_track_section = create_audio_track_section(audio_section_ptr); + audio_track_section_list_ptr->add_widget(std::move(audio_track_section)); } } void SettingsPage::load_common(RecordOptions &record_options) { record_area_box_ptr->set_selected_item(record_options.record_area_option); - if(split_audio_checkbox_ptr) - split_audio_checkbox_ptr->set_checked(!record_options.merge_audio_tracks); - application_audio_invert_checkbox_ptr->set_checked(record_options.application_audio_invert); change_video_resolution_checkbox_ptr->set_checked(record_options.change_video_resolution); load_audio_tracks(record_options); color_range_box_ptr->set_selected_item(record_options.color_range); @@ -1139,28 +1210,38 @@ namespace gsr { container_box_ptr->set_selected_item(config.streaming_config.custom.container); } - static void save_audio_tracks(std::vector<std::string> &audio_devices, List *audio_devices_list_ptr) { - audio_devices.clear(); - audio_devices_list_ptr->for_each_child_widget([&audio_devices](std::unique_ptr<Widget> &child_widget) { - List *audio_track_line = static_cast<List*>(child_widget.get()); - const AudioTrackType audio_track_type = (AudioTrackType)(uintptr_t)audio_track_line->userdata; - switch(audio_track_type) { - case AudioTrackType::DEVICE: { - ComboBox *audio_device_box = static_cast<ComboBox*>(audio_track_line->get_child_widget_by_index(1)); - audio_devices.push_back("device:" + audio_device_box->get_selected_id()); - break; - } - case AudioTrackType::APPLICATION: { - ComboBox *application_audio_box = static_cast<ComboBox*>(audio_track_line->get_child_widget_by_index(1)); - audio_devices.push_back("app:" + application_audio_box->get_selected_id()); - break; + static void save_audio_tracks(std::vector<AudioTrack> &audio_tracks, List *audio_track_section_list_ptr) { + audio_tracks.clear(); + audio_track_section_list_ptr->for_each_child_widget([&audio_tracks](std::unique_ptr<Widget> &child_widget) { + Subsection *audio_subsection = dynamic_cast<Subsection*>(child_widget.get()); + List *audio_track_section_items_list_ptr = dynamic_cast<List*>(audio_subsection->get_inner_widget()); + List *audio_input_list_ptr = dynamic_cast<List*>(audio_track_section_items_list_ptr->get_child_widget_by_index(2)); + CheckBox *application_audio_invert_checkbox_ptr = dynamic_cast<CheckBox*>(audio_track_section_items_list_ptr->get_child_widget_by_index(3)); + + audio_tracks.push_back({std::vector<std::string>{}, application_audio_invert_checkbox_ptr->is_checked()}); + audio_input_list_ptr->for_each_child_widget([&audio_tracks](std::unique_ptr<Widget> &child_widget){ + List *audio_track_line = dynamic_cast<List*>(child_widget.get()); + const AudioTrackType audio_track_type = (AudioTrackType)(uintptr_t)audio_track_line->userdata; + switch(audio_track_type) { + case AudioTrackType::DEVICE: { + ComboBox *audio_device_box = dynamic_cast<ComboBox*>(audio_track_line->get_child_widget_by_index(1)); + audio_tracks.back().audio_inputs.push_back("device:" + audio_device_box->get_selected_id()); + break; + } + case AudioTrackType::APPLICATION: { + ComboBox *application_audio_box = dynamic_cast<ComboBox*>(audio_track_line->get_child_widget_by_index(1)); + audio_tracks.back().audio_inputs.push_back("app:" + application_audio_box->get_selected_id()); + break; + } + case AudioTrackType::APPLICATION_CUSTOM: { + Entry *application_audio_entry = dynamic_cast<Entry*>(audio_track_line->get_child_widget_by_index(1)); + audio_tracks.back().audio_inputs.push_back("app:" + application_audio_entry->get_text()); + break; + } } - case AudioTrackType::APPLICATION_CUSTOM: { - Entry *application_audio_entry = static_cast<Entry*>(audio_track_line->get_child_widget_by_index(1)); - audio_devices.push_back("app:" + application_audio_entry->get_text()); - break; - } - } + return true; + }); + return true; }); } @@ -1173,11 +1254,8 @@ namespace gsr { record_options.video_height = atoi(video_height_entry_ptr->get_text().c_str()); record_options.fps = atoi(framerate_entry_ptr->get_text().c_str()); record_options.video_bitrate = atoi(video_bitrate_entry_ptr->get_text().c_str()); - if(split_audio_checkbox_ptr) - record_options.merge_audio_tracks = !split_audio_checkbox_ptr->is_checked(); - record_options.application_audio_invert = application_audio_invert_checkbox_ptr->is_checked(); record_options.change_video_resolution = change_video_resolution_checkbox_ptr->is_checked(); - save_audio_tracks(record_options.audio_tracks, audio_track_list_ptr); + save_audio_tracks(record_options.audio_tracks_list, audio_track_section_list_ptr); record_options.color_range = color_range_box_ptr->get_selected_id(); record_options.video_quality = video_quality_box_ptr->get_selected_id(); record_options.video_codec = video_codec_box_ptr->get_selected_id(); diff --git a/src/gui/StaticPage.cpp b/src/gui/StaticPage.cpp index 182464c..5147819 100644 --- a/src/gui/StaticPage.cpp +++ b/src/gui/StaticPage.cpp @@ -20,8 +20,9 @@ namespace gsr { // Process widgets by visibility (backwards) return widgets.for_each_reverse([selected_widget, &window, &event, offset](std::unique_ptr<Widget> &widget) { - if(widget.get() != selected_widget) { - if(!widget->on_event(event, window, offset)) + Widget *p = widget.get(); + if(p != selected_widget) { + if(!p->on_event(event, window, offset)) return false; } return true; diff --git a/src/gui/Subsection.cpp b/src/gui/Subsection.cpp index c97460e..bc75a9c 100644 --- a/src/gui/Subsection.cpp +++ b/src/gui/Subsection.cpp @@ -12,12 +12,17 @@ namespace gsr { static const float title_spacing_scale = 0.010f; Subsection::Subsection(const char *title, std::unique_ptr<Widget> inner_widget, mgl::vec2f size) : - label(&get_theme().title_font, title, get_color_theme().text_color), + label(&get_theme().title_font, title ? title : "", get_color_theme().text_color), inner_widget(std::move(inner_widget)), size(size) { this->inner_widget->parent_widget = this; } + + Subsection::~Subsection() { + if(inner_widget->parent_widget == this) + inner_widget->parent_widget = nullptr; + } bool Subsection::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f) { if(!visible) @@ -32,7 +37,7 @@ namespace gsr { mgl::vec2f draw_pos = position + offset; mgl::Rectangle background(draw_pos.floor(), get_size().floor()); - background.set_color(mgl::Color(25, 30, 34)); + background.set_color(bg_color); window.draw(background); draw_pos += mgl::vec2f(margin_left_scale, margin_top_scale) * mgl::vec2f(get_theme().window_height, get_theme().window_height); @@ -69,4 +74,12 @@ namespace gsr { const mgl::vec2f margin_size = mgl::vec2f(margin_left_scale + margin_right_scale, margin_top_scale + margin_bottom_scale) * mgl::vec2f(get_theme().window_height, get_theme().window_height); return get_size() - margin_size; } + + Widget* Subsection::get_inner_widget() { + return inner_widget.get(); + } + + void Subsection::set_bg_color(mgl::Color color) { + bg_color = color; + } }
\ No newline at end of file diff --git a/src/gui/Widget.cpp b/src/gui/Widget.cpp index 8732bd7..66cf193 100644 --- a/src/gui/Widget.cpp +++ b/src/gui/Widget.cpp @@ -1,14 +1,15 @@ #include "../../include/gui/Widget.hpp" +#include <vector> namespace gsr { + static std::vector<std::unique_ptr<Widget>> widgets_to_remove; + Widget::Widget() { } Widget::~Widget() { remove_widget_as_selected_in_parent(); - // if(parent_widget) - // parent_widget->remove_child_widget(this); } void Widget::set_position(mgl::vec2f position) { @@ -62,4 +63,15 @@ namespace gsr { void Widget::set_visible(bool visible) { this->visible = visible; } + + void add_widget_to_remove(std::unique_ptr<Widget> widget) { + widgets_to_remove.push_back(std::move(widget)); + } + + void remove_widgets_to_be_removed() { + for(size_t i = 0; i < widgets_to_remove.size(); ++i) { + widgets_to_remove[i].reset(); + } + widgets_to_remove.clear(); + } }
\ No newline at end of file |