mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
presets: minor UI fixes, add new controller profiles (#584)
## Link to GitHub Issue or related Pull Request, if one exists #579 ## Description of change * Fix profiles being loaded twice on tab switch * Add more default profiles for some controllers * Remove borders from tables since they look broken in software renderer * Add check boxes to import/export only certain parts of of a profile * Show device identifier string in drop down when applying profiles since some controllers have multiple identically named interfaces * Show completion message when action buttons are clicked (`Apply` button, `Clear all bindings` button both become disabled & shows `done` message)
This commit is contained in:
@@ -258,6 +258,10 @@ namespace overlay::windows {
|
||||
if (previous_games_selected != this->games_selected) {
|
||||
read_card();
|
||||
templates_cache_dirty = true;
|
||||
log_misc(
|
||||
"config",
|
||||
"game selection changed from {} to {}",
|
||||
previous_games_selected, this->games_selected);
|
||||
}
|
||||
|
||||
// tab selection
|
||||
@@ -576,13 +580,18 @@ namespace overlay::windows {
|
||||
|
||||
// did tab selection change?
|
||||
if (this->tab_selected != tab_selected_new) {
|
||||
log_misc(
|
||||
"config",
|
||||
"tab selection changed from {} to {}",
|
||||
static_cast<uint32_t>(this->tab_selected),
|
||||
static_cast<uint32_t>(tab_selected_new));
|
||||
|
||||
stop_lights_test();
|
||||
|
||||
this->tab_selected = tab_selected_new;
|
||||
buttons_many_active = false;
|
||||
buttons_many_index = -1;
|
||||
templates_cache_dirty = true;
|
||||
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
@@ -3297,7 +3306,7 @@ namespace overlay::windows {
|
||||
+ ImGui::GetFrameHeightWithSpacing() * 2 + ImGui::GetStyle().WindowPadding.y;
|
||||
float table_h = ImGui::GetContentRegionAvail().y - footer_h;
|
||||
if (ImGui::BeginTable("##AutoMatchTable", 3,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY,
|
||||
ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY,
|
||||
ImVec2(0, table_h))) {
|
||||
ImGui::TableSetupColumn("Device Light", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 30.f);
|
||||
@@ -4879,11 +4888,15 @@ namespace overlay::windows {
|
||||
};
|
||||
|
||||
// apply game buttons and keypad buttons
|
||||
apply_buttons(tmpl.buttons, games::get_buttons(this->games_selected_name));
|
||||
apply_buttons(tmpl.keypad_buttons, games::get_buttons_keypads(this->games_selected_name));
|
||||
if (this->apply_buttons) {
|
||||
apply_buttons(tmpl.buttons, games::get_buttons(this->games_selected_name));
|
||||
}
|
||||
if (this->apply_keypads) {
|
||||
apply_buttons(tmpl.keypad_buttons, games::get_buttons_keypads(this->games_selected_name));
|
||||
}
|
||||
|
||||
// apply analog bindings (device source only)
|
||||
if (!source_is_naive && !target_is_naive) {
|
||||
if (this->apply_analogs && !source_is_naive && !target_is_naive) {
|
||||
auto *analogs = games::get_analogs(this->games_selected_name);
|
||||
if (analogs) {
|
||||
for (auto &ta : tmpl.analogs) {
|
||||
@@ -4914,7 +4927,7 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
// apply light bindings (device source only)
|
||||
if (!source_is_naive && !target_is_naive) {
|
||||
if (this->apply_lights && !source_is_naive && !target_is_naive) {
|
||||
auto *lights = games::get_lights(this->games_selected_name);
|
||||
if (lights) {
|
||||
for (auto &tl : tmpl.lights) {
|
||||
@@ -4980,7 +4993,7 @@ namespace overlay::windows {
|
||||
// preset list table
|
||||
if (!templates_cache.empty()) {
|
||||
if (ImGui::BeginTable("TemplateList", 6,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp)) {
|
||||
ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp)) {
|
||||
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_None, 3.f);
|
||||
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_None, 1.f);
|
||||
@@ -5092,9 +5105,7 @@ namespace overlay::windows {
|
||||
if (templates_selected >= 0 && templates_selected < (int)templates_cache.size()) {
|
||||
const auto &t = templates_cache[templates_selected];
|
||||
|
||||
ImGui::Text("Apply preset \"%s\"", t.name.c_str());
|
||||
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1),
|
||||
"Overlay bindings are not affected.");
|
||||
ImGui::Text("Applying preset: \"%s\"", t.name.c_str());
|
||||
ImGui::Spacing();
|
||||
|
||||
// clear all button
|
||||
@@ -5102,22 +5113,57 @@ namespace overlay::windows {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextColored(ImVec4(1.f, 0.5f, 0.5f, 1.f),
|
||||
"Step 1: Reset all existing bindings (Caution! This can't be undone.)");
|
||||
ImGui::BeginDisabled(this->all_cleared);
|
||||
if (ImGui::Button("Clear All Bindings")) {
|
||||
clear_all_bindings();
|
||||
this->all_cleared = true;
|
||||
std::fill(this->template_is_applied.begin(), this->template_is_applied.end(), false);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SameLine();
|
||||
ImGui::HelpMarker(
|
||||
"Clears all game button, analog, and light bindings.");
|
||||
if (this->all_cleared) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextUnformatted("Done.");
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1),
|
||||
"Step 2: Apply bindings by source (one at a time)");
|
||||
"Step 2: Pick which groups to apply");
|
||||
ImGui::Spacing();
|
||||
bool selection_changed = false;
|
||||
selection_changed |= ImGui::Checkbox("Buttons", &this->apply_buttons);
|
||||
ImGui::SameLine();
|
||||
selection_changed |= ImGui::Checkbox("Keypads", &this->apply_keypads);
|
||||
ImGui::SameLine();
|
||||
selection_changed |= ImGui::Checkbox("Analogs", &this->apply_analogs);
|
||||
ImGui::SameLine();
|
||||
selection_changed |= ImGui::Checkbox("Lights", &this->apply_lights);
|
||||
if (selection_changed) {
|
||||
std::fill(this->template_is_applied.begin(), this->template_is_applied.end(), false);
|
||||
}
|
||||
|
||||
if (!this->apply_buttons && !this->apply_keypads &&
|
||||
!this->apply_analogs && !this->apply_lights) {
|
||||
ImGui::TextUnformatted("\nYou must select at least one group to apply.\n\n");
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Step 3: Pick devices to apply profiles");
|
||||
ImGui::Spacing();
|
||||
ImGui::TextUnformatted("Hint: hold a button on the controller, it'll turn green in the drop down.");
|
||||
ImGui::Spacing();
|
||||
|
||||
// list binding sources with target selection
|
||||
auto sources = t.get_binding_sources();
|
||||
const auto sources = t.get_binding_sources();
|
||||
if (sources.size() != template_save_sources.size()) {
|
||||
this->template_is_applied.resize(sources.size(), false);
|
||||
}
|
||||
|
||||
// build target device list: "Naive" + all connected devices
|
||||
std::vector<std::string> target_options;
|
||||
@@ -5140,13 +5186,16 @@ namespace overlay::windows {
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("TemplateSources", 4,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
||||
ImGuiTableFlags_SizingStretchProp)) {
|
||||
if (!apply_buttons && !apply_keypads && !apply_analogs && !apply_lights) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
|
||||
ImGui::TableSetupColumn("Source", ImGuiTableColumnFlags_None, 2.f);
|
||||
ImGui::TableSetupColumn("Apply As", ImGuiTableColumnFlags_None, 3.f);
|
||||
ImGui::TableSetupColumn("Status", ImGuiTableColumnFlags_None, 2.f);
|
||||
if (ImGui::BeginTable("TemplateSources", 4,
|
||||
ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp)) {
|
||||
|
||||
ImGui::TableSetupColumn("Profile", ImGuiTableColumnFlags_None, 2.f);
|
||||
ImGui::TableSetupColumn("Device", ImGuiTableColumnFlags_None, 3.f);
|
||||
ImGui::TableSetupColumn("Status", ImGuiTableColumnFlags_WidthFixed, overlay::apply_scaling(80));
|
||||
ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_None, 1.f);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
@@ -5159,30 +5208,44 @@ namespace overlay::windows {
|
||||
if (dev.hidInfo) {
|
||||
for (auto &page : dev.hidInfo->button_states) {
|
||||
for (bool s : page) {
|
||||
if (s) { pressed = true; break; }
|
||||
if (s) {
|
||||
pressed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pressed) {
|
||||
break;
|
||||
}
|
||||
if (pressed) { break; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case rawinput::KEYBOARD:
|
||||
if (dev.keyboardInfo) {
|
||||
for (bool s : dev.keyboardInfo->key_states) {
|
||||
if (s) { pressed = true; break; }
|
||||
if (s) {
|
||||
pressed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case rawinput::MOUSE:
|
||||
if (dev.mouseInfo) {
|
||||
for (bool s : dev.mouseInfo->key_states) {
|
||||
if (s) { pressed = true; break; }
|
||||
if (s) {
|
||||
pressed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case rawinput::MIDI:
|
||||
if (dev.midiInfo) {
|
||||
for (bool s : dev.midiInfo->states) {
|
||||
if (s) { pressed = true; break; }
|
||||
if (s) {
|
||||
pressed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -5204,6 +5267,7 @@ namespace overlay::windows {
|
||||
{
|
||||
int sel = template_target_selection[si];
|
||||
bool active = sel > 0 && active_devices.count(target_options[sel]) > 0;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
if (active) {
|
||||
ImGui::TextColored(ImVec4(0.f, 1.f, 0.f, 1.f), "%s", sources[si].c_str());
|
||||
} else {
|
||||
@@ -5218,7 +5282,7 @@ namespace overlay::windows {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
{
|
||||
int sel = template_target_selection[si];
|
||||
const int sel = template_target_selection[si];
|
||||
const char *preview = (sel >= 0) ? target_options[sel].c_str() : "(select target)";
|
||||
if (ImGui::BeginCombo("##target", preview)) {
|
||||
for (int ti = 0; ti < (int)target_options.size(); ti++) {
|
||||
@@ -5228,7 +5292,7 @@ namespace overlay::windows {
|
||||
if (ti > 0) {
|
||||
auto *dev = RI_MGR->devices_get(target_options[ti]);
|
||||
if (dev) {
|
||||
combo_label = fmt::format("{}##{}", dev->desc, dev->name);
|
||||
combo_label = fmt::format("{} ({})##{}", dev->desc.substr(0, 42), dev->name.substr(0, 36), dev->name);
|
||||
item_active = active_devices.count(dev->name) > 0;
|
||||
}
|
||||
}
|
||||
@@ -5245,6 +5309,7 @@ namespace overlay::windows {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
this->template_is_applied[si] = false;
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
@@ -5255,12 +5320,14 @@ namespace overlay::windows {
|
||||
int sel = template_target_selection[si];
|
||||
if (sel < 0) {
|
||||
ImGui::TextDisabled("--");
|
||||
} else if (this->template_is_applied[si]) {
|
||||
ImGui::TextColored(ImVec4(0.f, 1.f, 0.f, 1.f), "Applied!");
|
||||
} else if (target_options[sel] == "Naive") {
|
||||
ImGui::TextColored(ImVec4(0.f, 1.f, 0.f, 1.f), "OK");
|
||||
ImGui::TextUnformatted("Ready");
|
||||
} else {
|
||||
auto *device = RI_MGR->devices_get(target_options[sel]);
|
||||
if (device) {
|
||||
ImGui::TextColored(ImVec4(0.f, 1.f, 0.f, 1.f), "OK");
|
||||
ImGui::TextUnformatted("Ready");
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(1.f, 0.5f, 0.f, 1.f), "Not found");
|
||||
}
|
||||
@@ -5270,18 +5337,16 @@ namespace overlay::windows {
|
||||
// apply button
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
int sel = template_target_selection[si];
|
||||
if (sel < 0) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
const int sel = template_target_selection[si];
|
||||
ImGui::BeginDisabled(sel < 0 || this->template_is_applied[si]);
|
||||
if (ImGui::Button("Apply")) {
|
||||
if (sel >= 0) {
|
||||
apply_template_source(t, sources[si], target_options[sel]);
|
||||
this->template_is_applied[si] = true;
|
||||
this->all_cleared = false;
|
||||
}
|
||||
}
|
||||
if (sel < 0) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -5289,6 +5354,10 @@ namespace overlay::windows {
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
if (!apply_buttons && !apply_keypads && !apply_analogs && !apply_lights) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetWindowHeight()
|
||||
@@ -5296,6 +5365,7 @@ namespace overlay::windows {
|
||||
- ImGui::GetStyle().WindowPadding.y);
|
||||
if (ImGui::Button("Close")) {
|
||||
templates_selected = -1;
|
||||
all_cleared = false;
|
||||
template_target_selection.clear();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
@@ -5360,9 +5430,21 @@ namespace overlay::windows {
|
||||
"Labels replace device IDs in the saved preset.");
|
||||
ImGui::Spacing();
|
||||
|
||||
ImGui::TextUnformatted("Pick which groups to save:");
|
||||
ImGui::Checkbox("Buttons", &this->save_buttons);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Keypads", &this->save_keypads);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Analogs", &this->save_analogs);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Lights", &this->save_lights);
|
||||
if (!this->save_analogs && !this->save_keypads &&
|
||||
!this->save_analogs && !this->save_lights) {
|
||||
ImGui::TextUnformatted("\nYou must select at least one group to save.\n\n");
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("SaveLabels", 2,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
||||
ImGuiTableFlags_SizingStretchProp)) {
|
||||
ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp)) {
|
||||
|
||||
ImGui::TableSetupColumn("Source", ImGuiTableColumnFlags_None, 3.f);
|
||||
ImGui::TableSetupColumn("Label", ImGuiTableColumnFlags_None, 3.f);
|
||||
@@ -5405,16 +5487,19 @@ namespace overlay::windows {
|
||||
ImGui::SetCursorPosY(ImGui::GetWindowHeight()
|
||||
- ImGui::GetFrameHeightWithSpacing()
|
||||
- ImGui::GetStyle().WindowPadding.y);
|
||||
if (!all_labels_set) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(
|
||||
!all_labels_set ||
|
||||
(!this->save_buttons && !this->save_keypads && !this->save_analogs && !this->save_lights));
|
||||
|
||||
if (ImGui::Button("Save")) {
|
||||
// replace device IDs with labels in the template
|
||||
for (int si = 0; si < (int)template_save_sources.size(); si++) {
|
||||
template_pending_save.rename_source(
|
||||
template_save_sources[si], template_save_labels[si]);
|
||||
}
|
||||
if (save_user_template(template_pending_save)) {
|
||||
if (save_user_template(template_pending_save,
|
||||
this->save_buttons, this->save_keypads, this->save_analogs, this->save_lights)) {
|
||||
template_save_name[0] = '\0';
|
||||
templates_cache_dirty = true;
|
||||
}
|
||||
@@ -5422,9 +5507,7 @@ namespace overlay::windows {
|
||||
template_save_labels.clear();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (!all_labels_set) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
@@ -5446,8 +5529,7 @@ namespace overlay::windows {
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::BeginTable("EditLabels", 2,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
|
||||
ImGuiTableFlags_SizingStretchProp)) {
|
||||
ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp)) {
|
||||
|
||||
ImGui::TableSetupColumn("Current Label", ImGuiTableColumnFlags_None, 3.f);
|
||||
ImGui::TableSetupColumn("New Label", ImGuiTableColumnFlags_None, 3.f);
|
||||
@@ -5499,7 +5581,7 @@ namespace overlay::windows {
|
||||
t.rename_source(template_save_sources[si], template_save_labels[si]);
|
||||
}
|
||||
}
|
||||
save_user_template(t);
|
||||
save_user_template(t, true, true, true, true);
|
||||
templates_cache_dirty = true;
|
||||
template_save_sources.clear();
|
||||
template_save_labels.clear();
|
||||
|
||||
Reference in New Issue
Block a user