Add controller button icons in hotkeys, separate keyboard hotkeys and controller hotkeys

This commit is contained in:
dec05eba
2025-03-18 19:13:16 +01:00
parent 44e7f57d21
commit dc70bd27f2
16 changed files with 134 additions and 15 deletions

View File

@@ -38,7 +38,10 @@ This program has to grab all keyboards and create a virtual keyboard (`gsr-ui vi
This might cause issues for you if you use input remapping software. To workaround this you can go into settings and select "Only grab virtual devices" This might cause issues for you if you use input remapping software. To workaround this you can go into settings and select "Only grab virtual devices"
# License # License
This software is licensed under GPL3.0-only. Files under `fonts/` directory belong to the Noto Sans Google fonts project and they are licensed under `SIL Open Font License`. `images/default.cur` it part of the [Adwaita icon theme](https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/tree/master) which is licensed under `Creative Commons Attribution-Share Alike 3.0`. This software is licensed under GPL3.0-only. Files under `fonts/` directory belong to the Noto Sans Google fonts project and they are licensed under `SIL Open Font License`.\
`images/default.cur` it part of the [Adwaita icon theme](https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/tree/master) which is licensed under `CC BY-SA 3.0`.\
The D-Pad images under `images/` were created by [Julio Cacko](https://juliocacko.itch.io/free-input-prompts) and they are licensed under `CC0 1.0 Universal`.\
The PlayStation logo under `images/` was created by [ArksDigital](https://arks.itch.io/ps4-buttons) and it's are licensed under `CC BY 4.0`.
# Reporting bugs, contributing patches, questions or donation # Reporting bugs, contributing patches, questions or donation
See [https://git.dec05eba.com/?p=about](https://git.dec05eba.com/?p=about). See [https://git.dec05eba.com/?p=about](https://git.dec05eba.com/?p=about).

BIN
images/ps4_dpad_down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
images/ps4_dpad_left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
images/ps4_dpad_right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
images/ps4_dpad_up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
images/ps4_home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -43,6 +43,12 @@ namespace gsr {
mgl::Texture save_texture; mgl::Texture save_texture;
mgl::Texture screenshot_texture; mgl::Texture screenshot_texture;
mgl::Texture ps4_home_texture;
mgl::Texture ps4_dpad_up_texture;
mgl::Texture ps4_dpad_down_texture;
mgl::Texture ps4_dpad_left_texture;
mgl::Texture ps4_dpad_right_texture;
double double_click_timeout_seconds = 0.4; double double_click_timeout_seconds = 0.4;
// Reloads fonts // Reloads fonts

View File

@@ -4,7 +4,6 @@
#include <string_view> #include <string_view>
#include <map> #include <map>
#include <string> #include <string>
#include <optional>
namespace gsr { namespace gsr {
struct KeyValue { struct KeyValue {

View File

@@ -59,7 +59,8 @@ namespace gsr {
std::unique_ptr<List> create_stream_hotkey_options(); std::unique_ptr<List> create_stream_hotkey_options();
std::unique_ptr<List> create_screenshot_hotkey_options(); std::unique_ptr<List> create_screenshot_hotkey_options();
std::unique_ptr<List> create_hotkey_control_buttons(); std::unique_ptr<List> create_hotkey_control_buttons();
std::unique_ptr<Subsection> create_hotkey_subsection(ScrollablePage *parent_page); std::unique_ptr<Subsection> create_keyboard_hotkey_subsection(ScrollablePage *parent_page);
std::unique_ptr<Subsection> create_controller_hotkey_subsection(ScrollablePage *parent_page);
std::unique_ptr<Button> create_exit_program_button(); std::unique_ptr<Button> create_exit_program_button();
std::unique_ptr<Button> create_go_back_to_old_ui_button(); std::unique_ptr<Button> create_go_back_to_old_ui_button();
std::unique_ptr<Subsection> create_application_options_subsection(ScrollablePage *parent_page); std::unique_ptr<Subsection> create_application_options_subsection(ScrollablePage *parent_page);

29
include/gui/Image.hpp Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include "Widget.hpp"
#include <mglpp/graphics/Sprite.hpp>
namespace gsr {
class Image : public Widget {
public:
enum class ScaleBehavior {
SCALE,
CLAMP
};
// Set size to {0.0f, 0.0f} for no limit. The image is scaled to the size while keeping its aspect ratio
Image(mgl::Texture *texture, mgl::vec2f size, ScaleBehavior scale_behavior);
Image(const Image&) = delete;
Image& operator=(const Image&) = delete;
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() override;
private:
mgl::Sprite sprite;
mgl::vec2f size;
ScaleBehavior scale_behavior;
};
}

View File

@@ -3,9 +3,6 @@
#include <mglpp/system/vec.hpp> #include <mglpp/system/vec.hpp>
#include <mglpp/graphics/Color.hpp> #include <mglpp/graphics/Color.hpp>
#include <functional>
#include <string_view>
namespace mgl { namespace mgl {
class Window; class Window;
} }
@@ -16,4 +13,5 @@ namespace gsr {
double get_frame_delta_seconds(); double get_frame_delta_seconds();
void set_frame_delta_seconds(double frame_delta); void set_frame_delta_seconds(double frame_delta);
mgl::vec2f scale_keep_aspect_ratio(mgl::vec2f from, mgl::vec2f to); mgl::vec2f scale_keep_aspect_ratio(mgl::vec2f from, mgl::vec2f to);
mgl::vec2f clamp_keep_aspect_ratio(mgl::vec2f from, mgl::vec2f to);
} }

View File

@@ -23,6 +23,7 @@ src = [
'src/gui/Utils.cpp', 'src/gui/Utils.cpp',
'src/gui/DropdownButton.cpp', 'src/gui/DropdownButton.cpp',
'src/gui/Label.cpp', 'src/gui/Label.cpp',
'src/gui/Image.cpp',
'src/gui/LineSeparator.cpp', 'src/gui/LineSeparator.cpp',
'src/gui/CustomRendererWidget.cpp', 'src/gui/CustomRendererWidget.cpp',
'src/gui/FileChooser.cpp', 'src/gui/FileChooser.cpp',

View File

@@ -111,6 +111,21 @@ namespace gsr {
if(!theme->screenshot_texture.load_from_file((resources_path + "images/screenshot.png").c_str())) if(!theme->screenshot_texture.load_from_file((resources_path + "images/screenshot.png").c_str()))
goto error; goto error;
if(!theme->ps4_home_texture.load_from_file((resources_path + "images/ps4_home.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
goto error;
if(!theme->ps4_dpad_up_texture.load_from_file((resources_path + "images/ps4_dpad_up.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
goto error;
if(!theme->ps4_dpad_down_texture.load_from_file((resources_path + "images/ps4_dpad_down.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
goto error;
if(!theme->ps4_dpad_left_texture.load_from_file((resources_path + "images/ps4_dpad_left.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
goto error;
if(!theme->ps4_dpad_right_texture.load_from_file((resources_path + "images/ps4_dpad_right.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
goto error;
return true; return true;
error: error:

View File

@@ -10,6 +10,7 @@
#include "../../include/gui/Subsection.hpp" #include "../../include/gui/Subsection.hpp"
#include "../../include/gui/List.hpp" #include "../../include/gui/List.hpp"
#include "../../include/gui/Label.hpp" #include "../../include/gui/Label.hpp"
#include "../../include/gui/Image.hpp"
#include "../../include/gui/RadioButton.hpp" #include "../../include/gui/RadioButton.hpp"
#include "../../include/gui/LineSeparator.hpp" #include "../../include/gui/LineSeparator.hpp"
#include "../../include/gui/CustomRendererWidget.hpp" #include "../../include/gui/CustomRendererWidget.hpp"
@@ -325,29 +326,48 @@ namespace gsr {
return list; return list;
} }
std::unique_ptr<Subsection> GlobalSettingsPage::create_hotkey_subsection(ScrollablePage *parent_page) { static std::unique_ptr<List> create_joystick_hotkey_text(mgl::Texture *image1, mgl::Texture *image2, float max_height, const char *suffix) {
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Press", get_color_theme().text_color));
list->add_widget(std::make_unique<Image>(image1, mgl::vec2f{max_height, 1000.0f}, Image::ScaleBehavior::SCALE));
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "and", get_color_theme().text_color));
list->add_widget(std::make_unique<Image>(image2, mgl::vec2f{max_height, 1000.0f}, Image::ScaleBehavior::SCALE));
list->add_widget(std::make_unique<Label>(&get_theme().body_font, suffix, get_color_theme().text_color));
return list;
}
std::unique_ptr<Subsection> GlobalSettingsPage::create_keyboard_hotkey_subsection(ScrollablePage *parent_page) {
auto list = std::make_unique<List>(List::Orientation::VERTICAL); auto list = std::make_unique<List>(List::Orientation::VERTICAL);
List *list_ptr = list.get(); List *list_ptr = list.get();
auto subsection = std::make_unique<Subsection>("Hotkeys", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f)); auto subsection = std::make_unique<Subsection>("Keyboard hotkeys", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Enable keyboard hotkeys?", get_color_theme().text_color)); list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Enable keyboard hotkeys?", get_color_theme().text_color));
list_ptr->add_widget(create_enable_keyboard_hotkeys_button()); list_ptr->add_widget(create_enable_keyboard_hotkeys_button());
list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Enable controller hotkeys?", get_color_theme().text_color));
list_ptr->add_widget(create_enable_joystick_hotkeys_button());
list_ptr->add_widget(std::make_unique<LineSeparator>(LineSeparator::Orientation::HORIZONTAL, subsection->get_inner_size().x)); 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_show_hide_hotkey_options());
list_ptr->add_widget(create_replay_hotkey_options()); list_ptr->add_widget(create_replay_hotkey_options());
list_ptr->add_widget(create_record_hotkey_options()); list_ptr->add_widget(create_record_hotkey_options());
list_ptr->add_widget(create_stream_hotkey_options()); list_ptr->add_widget(create_stream_hotkey_options());
list_ptr->add_widget(create_screenshot_hotkey_options()); list_ptr->add_widget(create_screenshot_hotkey_options());
list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Press the PlayStation button and d-pad up to take a screenshot", get_color_theme().text_color));
list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Press the PlayStation button and d-pad down to save a replay", get_color_theme().text_color));
list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Press the PlayStation button and d-pad left to start/stop recording", get_color_theme().text_color));
list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Press the PlayStation button and d-pad right to start/stop replay", get_color_theme().text_color));
list_ptr->add_widget(create_hotkey_control_buttons()); list_ptr->add_widget(create_hotkey_control_buttons());
return subsection; return subsection;
} }
std::unique_ptr<Subsection> GlobalSettingsPage::create_controller_hotkey_subsection(ScrollablePage *parent_page) {
auto list = std::make_unique<List>(List::Orientation::VERTICAL);
List *list_ptr = list.get();
auto subsection = std::make_unique<Subsection>("Controller hotkeys", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
list_ptr->add_widget(std::make_unique<Label>(&get_theme().body_font, "Enable controller hotkeys?", get_color_theme().text_color));
list_ptr->add_widget(create_enable_joystick_hotkeys_button());
list_ptr->add_widget(std::make_unique<LineSeparator>(LineSeparator::Orientation::HORIZONTAL, subsection->get_inner_size().x));
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_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;
}
std::unique_ptr<Button> GlobalSettingsPage::create_exit_program_button() { std::unique_ptr<Button> GlobalSettingsPage::create_exit_program_button() {
auto exit_program_button = std::make_unique<Button>(&get_theme().body_font, "Exit program", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120)); auto exit_program_button = std::make_unique<Button>(&get_theme().body_font, "Exit program", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
exit_program_button->on_click = [&]() { exit_program_button->on_click = [&]() {
@@ -405,7 +425,8 @@ namespace gsr {
settings_list->set_spacing(0.018f); settings_list->set_spacing(0.018f);
settings_list->add_widget(create_appearance_subsection(scrollable_page.get())); settings_list->add_widget(create_appearance_subsection(scrollable_page.get()));
settings_list->add_widget(create_startup_subsection(scrollable_page.get())); settings_list->add_widget(create_startup_subsection(scrollable_page.get()));
settings_list->add_widget(create_hotkey_subsection(scrollable_page.get())); settings_list->add_widget(create_keyboard_hotkey_subsection(scrollable_page.get()));
settings_list->add_widget(create_controller_hotkey_subsection(scrollable_page.get()));
settings_list->add_widget(create_application_options_subsection(scrollable_page.get())); settings_list->add_widget(create_application_options_subsection(scrollable_page.get()));
settings_list->add_widget(create_application_info_subsection(scrollable_page.get())); settings_list->add_widget(create_application_info_subsection(scrollable_page.get()));
scrollable_page->add_widget(std::move(settings_list)); scrollable_page->add_widget(std::move(settings_list));

39
src/gui/Image.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "../../include/gui/Image.hpp"
#include "../../include/gui/Utils.hpp"
#include <mglpp/window/Window.hpp>
#include <mglpp/graphics/Texture.hpp>
namespace gsr {
Image::Image(mgl::Texture *texture, mgl::vec2f size, ScaleBehavior scale_behavior) :
sprite(texture), size(size), scale_behavior(scale_behavior)
{
}
bool Image::on_event(mgl::Event&, mgl::Window&, mgl::vec2f) {
return true;
}
void Image::draw(mgl::Window &window, mgl::vec2f offset) {
if(!visible)
return;
sprite.set_size(get_size());
sprite.set_position((position + offset).floor());
window.draw(sprite);
}
mgl::vec2f Image::get_size() {
if(!visible || !sprite.get_texture())
return {0.0f, 0.0f};
const mgl::vec2f sprite_size = sprite.get_texture()->get_size().to_vec2f();
if(size.x < 0.001f && size.y < 0.001f)
return sprite_size;
else if(scale_behavior == ScaleBehavior::SCALE)
return scale_keep_aspect_ratio(sprite_size, size);
else
return clamp_keep_aspect_ratio(sprite_size, size);
}
}

View File

@@ -67,4 +67,11 @@ namespace gsr {
return from; return from;
} }
mgl::vec2f clamp_keep_aspect_ratio(mgl::vec2f from, mgl::vec2f to) {
if(from.x > to.x || from.y > to.y)
return scale_keep_aspect_ratio(from, to);
else
return from;
}
} }