overlay: remove multiple pages from Buttons/Overlay/Lights tabs, replace with tree layout (#541)

The old pages UI was not intuitive and often led to questions like:

* How do I bind multiple controllers to a single input?? (failure to
discover)
* I have a ghost input that won't go away, how do I fix this? Is this a
bug? (non-intuitive UI - there are too many pages and finding out where
each binding is potentially requires scrolling through 100 pages)
* Potential perf issue - user binds too many by accident, or puts
bindings all the way in page 99, requiring us to walk each element in
the vector, wasting precious CPU cycles during an input poll.

This PR removes the multiple pages, and puts everything on a single
page, showing multiple binds in a tree structure.

It also puts a hard limit on how many alternate bindings can be made (8
for buttons, 16 for lights), though if the user has configured more in
older version they will be respected.
This commit is contained in:
bicarus
2026-01-31 15:16:19 -08:00
committed by GitHub
parent 927170ce73
commit 4d32dde83e
4 changed files with 337 additions and 142 deletions
+22 -12
View File
@@ -38,7 +38,6 @@ namespace overlay::windows {
ConfigTab tab_selected = ConfigTab::CONFIG_TAB_INVALID;
// buttons tab
int buttons_page = 0;
bool buttons_keyboard_state[0xFF];
bool buttons_bind_active = false;
bool buttons_many_active = false;
@@ -46,6 +45,9 @@ namespace overlay::windows {
bool buttons_many_naive = false;
int buttons_many_delay = 0;
int buttons_many_index = -1;
bool io_allow_multi_binding = false;
bool io_has_valid_alternatives = false;
void inc_buttons_many_index(int index_max);
@@ -55,7 +57,6 @@ namespace overlay::windows {
int analogs_devices_control_selected = -1;
// lights tab
int lights_page = 0;
std::vector<rawinput::Device *> lights_devices;
int lights_devices_selected = -1;
int lights_devices_control_selected = -1;
@@ -79,24 +80,32 @@ namespace overlay::windows {
std::string search_filter_in_lower_case = "";
void build_buttons(const std::string &name, std::vector<Button> *buttons, int min = 0, int max = -1);
void build_button(const std::string &name, Button *button, const int button_it, const int button_it_max);
void bind_button_popup(const std::string &bind_name, Button *button, const int button_it_max);
void naive_button_popup(const std::string &naive_string, Button *button, const int button_it_max);
void build_button(
const std::string &name,
Button &primary_button,
Button *button,
const int button_it,
const int button_it_max,
const int alt_index);
void bind_button_popup(const std::string &bind_name, Button *button, const int button_it_max, const int alt_index);
void naive_button_popup(const std::string &naive_string, Button *button, const int button_it_max, const int alt_index);
void edit_button_popup(
const std::string &edit_name,
const std::string &button_display,
Button *button,
const GameAPI::Buttons::State button_state,
const float button_velocity);
void clear_button(Button *button);
const float button_velocity,
const int alt_index);
void clear_button(Button *button, const int alt_index);
void bind_multiple_checkbox();
void build_analogs(const std::string &name, std::vector<Analog> *analogs);
void edit_analog_popup(Analog &analog);
void build_lights(const std::string &name, std::vector<Light> *lights);
void build_light(Light *light);
void clear_light(Light *light);
void edit_light_popup(Light *light);
void build_light(Light &primary_light, Light *light, const int light_index, const int alt_index);
void clear_light(Light *light, const int alt_index);
void edit_light_popup(Light &primary_light, Light *light, const int alt_index);
void build_cards();
void build_options(
@@ -105,10 +114,11 @@ namespace overlay::windows {
void build_launcher();
void launch_shell(LPCSTR app, LPCSTR file=nullptr);
void build_page_selector(int *page);
void build_menu(int *game_selected);
void shutdown_system(bool force, bool reboot_instead);
void set_alternating_row_colors(const int row_index);
public:
Config(SpiceOverlay *overlay);
~Config() override;