#pragma once #include #include #include "cfg/game.h" #include "overlay/window.h" #include "rawinput/device.h" #include "external/imgui/imgui_filebrowser.h" #include "patch_manager.h" #include "controller_presets.h" namespace overlay::windows { // top-level tabs in the configuration window enum class ConfigTab { CONFIG_TAB_INVALID, CONFIG_TAB_CONTROLLER, CONFIG_TAB_CARDS, CONFIG_TAB_PATCHES, CONFIG_TAB_OPTIONS, }; // sub-pages shown in the Controller tab's left navigation enum class ControllerPage { CONTROLLER_PAGE_INVALID, CONTROLLER_PAGE_BUTTONS, CONTROLLER_PAGE_KEYPADS, CONTROLLER_PAGE_ANALOGS, CONTROLLER_PAGE_OVERLAY, CONTROLLER_PAGE_LIGHTS, CONTROLLER_PAGE_PRESETS, }; struct MatchEntry { std::string game_name; std::string device_name; int light_index; int control_index; bool soft; }; class Config : public Window { private: // game selection int games_selected = -1; std::string games_selected_name = ""; std::vector games_list; std::vector games_names; // currently selected top-level tab and Controller sub-page ConfigTab tab_selected = ConfigTab::CONFIG_TAB_INVALID; ControllerPage controller_page_selected = ControllerPage::CONTROLLER_PAGE_INVALID; // buttons tab bool buttons_keyboard_state[0xFF]; bool buttons_bind_active = false; bool buttons_many_active = false; std::string buttons_many_active_section = ""; bool buttons_many_naive = false; int buttons_many_delay = 0; int buttons_many_index = -1; void inc_buttons_many_index(int index_max); // analogs tab std::vector analogs_devices; int analogs_devices_selected = -1; int analogs_devices_control_selected = -1; // lights tab std::vector lights_devices; int lights_devices_selected = -1; int lights_devices_control_selected = -1; // lights test all bool lights_testing = false; int lights_test_current = -1; std::chrono::steady_clock::time_point lights_test_time; // lights auto match std::vector auto_match_devices; int auto_match_device_selected = -1; bool auto_match_testing = false; int auto_match_test_current = -1; std::chrono::steady_clock::time_point auto_match_test_time; std::string auto_match_test_device; unsigned int auto_match_test_control = 0; std::chrono::steady_clock::time_point auto_match_copy_time; bool auto_match_copied = false; bool auto_match_soft_enabled = true; bool auto_match_p2 = false; // cards tab int keypads_selected[2] {}; char keypads_card_path[2][1024] {}; std::thread *keypads_card_select = nullptr; bool keypads_card_select_done = false; ImGui::FileBrowser keypads_card_select_browser[2]; char keypads_card_number[2][18] {}; bool keypads_card_override_valid[2] = { false, false }; bool keypads_card_file_contents_valid[2] = { false, false }; bool keypads_card_overwrite_confirmed[2]; // presets tab std::vector templates_cache; bool templates_cache_dirty = true; int templates_selected = -1; char template_save_name[256] = {}; // per-source target mapping: source index -> selected target device index std::vector template_target_selection; // deferred popup flags (to avoid ImGui ID stack mismatch inside tables) bool template_apply_open = false; bool template_edit_open = false; bool template_save_labels_open = false; bool template_delete_open = false; ControllerTemplate template_pending_save; std::vector template_save_sources; std::vector template_save_labels; bool apply_buttons = true; bool apply_keypads = true; bool apply_analogs = true; bool apply_lights = true; bool save_buttons = true; bool save_keypads = true; bool save_analogs = true; bool save_lights = true; bool all_cleared = false; std::vector template_is_applied; // patches tab std::unique_ptr patch_manager; // options tab bool options_show_hidden = false; bool options_dirty = false; int options_category = 0; std::string search_filter = ""; std::string search_filter_in_lower_case = ""; // Options tab left-nav: selected group, currently highlighted category, and a pending scroll std::string options_group_selected = ""; std::string options_category_selected = ""; bool options_scroll_pending = false; bool options_scroll_top = false; // Controller tab left-nav: selected sub-page std::string controller_page_label = ""; // Cards tab left-nav: selected sub-page std::string cards_page_label = ""; std::filesystem::path file_picker_path; std::thread *file_picker_thread = nullptr; bool file_picker_done = false; std::pair analog_as_button_warning_show_next_frame = { "", 0 }; void build_buttons(const std::string &name, std::vector