overlay: refactor UI code for I/O binding tabs (#533)

No functional changes, refactor of code only.
This commit is contained in:
bicarus
2026-01-26 22:24:14 -08:00
committed by GitHub
parent f0f46296f2
commit 1517cf9a7c
2 changed files with 1601 additions and 1559 deletions
+137 -110
View File
@@ -602,12 +602,18 @@ namespace overlay::windows {
// check buttons
if (buttons) {
int button_it_max = max < 0 ? buttons->size() - 1 : std::min((int) buttons->size() - 1, max);
const int button_it_max = max < 0 ? buttons->size() - 1 : std::min((int) buttons->size() - 1, max);
for (int button_it = min; button_it <= button_it_max; button_it++) {
auto &button_in = buttons->at(button_it);
build_button(name, &buttons->at(button_it), button_it, button_it_max);
}
}
ImGui::EndTable();
}
}
void Config::build_button(const std::string &name, Button *button, const int button_it, const int button_it_max) {
// get button based on page
auto button = &button_in;
auto &button_alternatives = button->getAlternatives();
if (this->buttons_page > 0) {
while ((int) button_alternatives.size() < this->buttons_page) {
@@ -621,10 +627,10 @@ namespace overlay::windows {
// get button info
ImGui::PushID(button);
auto button_name = button->getName();
auto button_display = button->getDisplayString(RI_MGR.get());
auto button_state = GameAPI::Buttons::getState(RI_MGR, *button);
auto button_velocity = GameAPI::Buttons::getVelocity(RI_MGR, *button);
const auto button_name = button->getName();
const auto button_display = button->getDisplayString(RI_MGR.get());
const auto button_state = GameAPI::Buttons::getState(RI_MGR, *button);
const auto button_velocity = GameAPI::Buttons::getVelocity(RI_MGR, *button);
// list entry
bool style_color = false;
@@ -707,8 +713,70 @@ namespace overlay::windows {
"Use 'Naive' for device independent binding using GetAsyncKeyState.");
}
if (ImGui::BeginPopupModal(bind_name.c_str(), NULL,
ImGuiWindowFlags_AlwaysAutoResize)) {
bind_button_popup(bind_name, button, button_it_max);
// naive binding
ImGui::SameLine();
std::string naive_string = "Naive " + button_name;
if (ImGui::Button("Naive")
|| (buttons_many_active && buttons_many_active_section == name && !buttons_bind_active
&& buttons_many_naive && buttons_many_index == button_it
&& ++buttons_many_delay > 25)) {
ImGui::OpenPopup(naive_string.c_str());
if (buttons_many_active) {
buttons_many_index = button_it;
buttons_many_naive = true;
buttons_many_delay = 0;
buttons_many_active_section = name;
}
// grab current keyboard state
for (unsigned short int i = 0x01; i < 0xFF; i++) {
buttons_keyboard_state[i] = GetAsyncKeyState(i) != 0;
}
}
if (ImGui::IsItemHovered()) {
ImGui::HelpTooltip(
"Use 'Bind' to bind a button to a device using RawInput.\n"
"Use 'Naive' for device independent binding using GetAsyncKeyState.");
}
naive_button_popup(naive_string, button, button_it_max);
// edit button
ImGui::SameLine();
std::string edit_name = "Edit " + button->getName();
if (ImGui::Button("Edit")) {
ImGui::OpenPopup(edit_name.c_str());
}
edit_button_popup(edit_name, button_display, button, button_state, button_velocity);
// clear button
if (button_display.size() > 0) {
ImGui::SameLine();
if (ImGui::Button("Clear")) {
button->setDeviceIdentifier("");
button->setVKey(0xFF);
button->setAnalogType(BAT_NONE);
button->setDebounceUp(0.0);
button->setDebounceDown(0.0);
button->setVelocityThreshold(0);
button->setInvert(false);
button->setLastState(GameAPI::Buttons::BUTTON_NOT_PRESSED);
button->setLastVelocity(0);
::Config::getInstance().updateBinding(
games_list[games_selected], *button,
buttons_page - 1);
}
}
// clean up
ImGui::PopID();
}
void Config::bind_button_popup(const std::string &bind_name, Button *button, const int button_it_max) {
if (ImGui::BeginPopupModal(bind_name.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
// modal content
ImGui::Text("Please press any button.");
@@ -1093,33 +1161,9 @@ namespace overlay::windows {
// clean up
ImGui::EndPopup();
}
// naive binding
ImGui::SameLine();
std::string naive_string = "Naive " + button_name;
if (ImGui::Button("Naive")
|| (buttons_many_active && buttons_many_active_section == name && !buttons_bind_active
&& buttons_many_naive && buttons_many_index == button_it
&& ++buttons_many_delay > 25)) {
ImGui::OpenPopup(naive_string.c_str());
if (buttons_many_active) {
buttons_many_index = button_it;
buttons_many_naive = true;
buttons_many_delay = 0;
buttons_many_active_section = name;
}
// grab current keyboard state
for (unsigned short int i = 0x01; i < 0xFF; i++) {
buttons_keyboard_state[i] = GetAsyncKeyState(i) != 0;
}
}
if (ImGui::IsItemHovered()) {
ImGui::HelpTooltip(
"Use 'Bind' to bind a button to a device using RawInput.\n"
"Use 'Naive' for device independent binding using GetAsyncKeyState.");
}
void Config::naive_button_popup(const std::string &naive_string, Button *button, const int button_it_max) {
if (ImGui::BeginPopupModal(naive_string.c_str(), NULL,
ImGuiWindowFlags_AlwaysAutoResize)) {
buttons_bind_active = true;
@@ -1180,13 +1224,15 @@ namespace overlay::windows {
}
ImGui::EndPopup();
}
// edit button
ImGui::SameLine();
std::string edit_name = "Edit " + button->getName();
if (ImGui::Button("Edit")) {
ImGui::OpenPopup(edit_name.c_str());
}
void Config::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) {
if (ImGui::BeginPopupModal(edit_name.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
bool dirty = false;
auto device = RI_MGR->devices_get(button->getDeviceIdentifier());
@@ -1619,33 +1665,6 @@ namespace overlay::windows {
}
ImGui::EndPopup();
}
// clear button
if (button_display.size() > 0) {
ImGui::SameLine();
if (ImGui::Button("Clear")) {
button->setDeviceIdentifier("");
button->setVKey(0xFF);
button->setAnalogType(BAT_NONE);
button->setDebounceUp(0.0);
button->setDebounceDown(0.0);
button->setVelocityThreshold(0);
button->setInvert(false);
button->setLastState(GameAPI::Buttons::BUTTON_NOT_PRESSED);
button->setLastVelocity(0);
::Config::getInstance().updateBinding(
games_list[games_selected], *button,
buttons_page - 1);
}
}
// clean up
ImGui::PopID();
}
}
ImGui::EndTable();
}
}
void Config::build_analogs(const std::string &name, std::vector<Analog> *analogs) {
@@ -1727,8 +1746,31 @@ namespace overlay::windows {
}
}
}
if (ImGui::BeginPopupModal("Analog Binding", NULL,
ImGuiWindowFlags_AlwaysAutoResize)) {
edit_analog_popup(analog);
// clear analog
if (analog_display.size() > 0) {
ImGui::SameLine();
if (ImGui::Button("Clear")) {
analog.clearBindings();
analog.setLastState(0.f);
::Config::getInstance().updateBinding(
games_list[games_selected], analog);
}
}
// clean up
ImGui::PopID();
}
}
ImGui::EndTable();
}
}
void Config::edit_analog_popup(Analog &analog) {
if (ImGui::BeginPopupModal("Analog Binding", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
// device selector
auto analog_device_changed = ImGui::Combo(
@@ -2069,25 +2111,6 @@ namespace overlay::windows {
// clean up
ImGui::EndPopup();
}
// clear analog
if (analog_display.size() > 0) {
ImGui::SameLine();
if (ImGui::Button("Clear")) {
analog.clearBindings();
analog.setLastState(0.f);
::Config::getInstance().updateBinding(
games_list[games_selected], analog);
}
}
// clean up
ImGui::PopID();
}
}
ImGui::EndTable();
}
}
void Config::build_lights(const std::string &name, std::vector<Light> *lights) {
@@ -2185,8 +2208,32 @@ namespace overlay::windows {
}
}
}
if (ImGui::BeginPopupModal("Light Binding", NULL,
ImGuiWindowFlags_AlwaysAutoResize)) {
edit_light_popup(light);
// clear light
if (light_display.size() > 0) {
ImGui::SameLine();
if (ImGui::Button("Clear")) {
light->setDeviceIdentifier("");
light->setIndex(0xFF);
::Config::getInstance().updateBinding(
games_list[games_selected], *light,
lights_page - 1);
}
}
// clean up
ImGui::PopID();
}
}
ImGui::EndTable();
}
}
void Config::edit_light_popup(Light *light) {
if (ImGui::BeginPopupModal("Light Binding", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
// device selector
bool control_changed = false;
@@ -2357,26 +2404,6 @@ namespace overlay::windows {
// clean up
ImGui::EndPopup();
}
// clear light
if (light_display.size() > 0) {
ImGui::SameLine();
if (ImGui::Button("Clear")) {
light->setDeviceIdentifier("");
light->setIndex(0xFF);
::Config::getInstance().updateBinding(
games_list[games_selected], *light,
lights_page - 1);
}
}
// clean up
ImGui::PopID();
}
}
ImGui::EndTable();
}
}
void Config::build_cards() {
+24 -9
View File
@@ -78,17 +78,23 @@ namespace overlay::windows {
std::string search_filter = "";
std::string search_filter_in_lower_case = "";
public:
Config(SpiceOverlay *overlay);
~Config() override;
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 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 read_card(int player = -1);
void write_card(int player);
void build_content() override;
void build_buttons(const std::string &name, std::vector<Button> *buttons,
int min = 0, int max = -1);
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 edit_light_popup(Light *light);
void build_cards();
void build_options(
std::vector<Option> *options, const std::string &category, const std::string *filter=nullptr);
@@ -96,8 +102,17 @@ namespace overlay::windows {
void build_launcher();
void launch_shell(LPCSTR app, LPCSTR file=nullptr);
static void build_page_selector(int *page);
void build_page_selector(int *page);
void build_menu(int *game_selected);
void shutdown_system(bool force, bool reboot_instead);
public:
Config(SpiceOverlay *overlay);
~Config() override;
void read_card(int player = -1);
void write_card(int player);
void build_content() override;
};
}