diff --git a/src/spice2x/build/controller_presets.xml b/src/spice2x/build/controller_presets.xml
index c447639..9c23bde 100644
--- a/src/spice2x/build/controller_presets.xml
+++ b/src/spice2x/build/controller_presets.xml
@@ -1,7 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/spice2x/cfg/controller_presets.cpp b/src/spice2x/cfg/controller_presets.cpp
index 4e9500b..0729e33 100644
--- a/src/spice2x/cfg/controller_presets.cpp
+++ b/src/spice2x/cfg/controller_presets.cpp
@@ -121,7 +121,9 @@ namespace overlay::windows {
std::vector templates;
auto *root = doc.RootElement();
- if (!root) return templates;
+ if (!root) {
+ return templates;
+ }
auto *tmpl_el = root->FirstChildElement("template");
while (tmpl_el) {
@@ -234,7 +236,13 @@ namespace overlay::windows {
return load_templates_from_doc(doc, false);
}
- bool save_user_template(const ControllerTemplate &tmpl) {
+ bool save_user_template(
+ const ControllerTemplate &tmpl,
+ const bool save_buttons,
+ const bool save_keypads,
+ const bool save_analogs,
+ const bool save_lights) {
+
auto path = get_templates_path();
auto path_tmp = path;
path_tmp.replace_extension(L"tmp");
@@ -273,13 +281,15 @@ namespace overlay::windows {
// buttons — skip unbound entries
auto *buttons_el = doc.NewElement("buttons");
- for (auto &btn : tmpl.buttons) {
- if (!btn.primary.is_unbound()) {
- write_button_entry(doc, buttons_el, btn.name, btn.primary);
- }
- for (auto &alt : btn.alternatives) {
- if (!alt.is_unbound()) {
- write_button_entry(doc, buttons_el, btn.name, alt);
+ if (save_buttons) {
+ for (auto &btn : tmpl.buttons) {
+ if (!btn.primary.is_unbound()) {
+ write_button_entry(doc, buttons_el, btn.name, btn.primary);
+ }
+ for (auto &alt : btn.alternatives) {
+ if (!alt.is_unbound()) {
+ write_button_entry(doc, buttons_el, btn.name, alt);
+ }
}
}
}
@@ -288,13 +298,15 @@ namespace overlay::windows {
// keypad buttons — skip unbound entries
if (!tmpl.keypad_buttons.empty()) {
auto *kp_el = doc.NewElement("keypad_buttons");
- for (auto &btn : tmpl.keypad_buttons) {
- if (!btn.primary.is_unbound()) {
- write_button_entry(doc, kp_el, btn.name, btn.primary);
- }
- for (auto &alt : btn.alternatives) {
- if (!alt.is_unbound()) {
- write_button_entry(doc, kp_el, btn.name, alt);
+ if (save_keypads) {
+ for (auto &btn : tmpl.keypad_buttons) {
+ if (!btn.primary.is_unbound()) {
+ write_button_entry(doc, kp_el, btn.name, btn.primary);
+ }
+ for (auto &alt : btn.alternatives) {
+ if (!alt.is_unbound()) {
+ write_button_entry(doc, kp_el, btn.name, alt);
+ }
}
}
}
@@ -303,22 +315,26 @@ namespace overlay::windows {
// analogs — skip unbound entries
auto *analogs_el = doc.NewElement("analogs");
- for (auto &a : tmpl.analogs) {
- if (!a.is_unbound()) {
- write_analog(doc, analogs_el, a);
+ if (save_analogs) {
+ for (auto &a : tmpl.analogs) {
+ if (!a.is_unbound()) {
+ write_analog(doc, analogs_el, a);
+ }
}
}
tmpl_el->InsertEndChild(analogs_el);
// lights — skip unbound entries
auto *lights_el = doc.NewElement("lights");
- for (auto &l : tmpl.lights) {
- if (!l.primary.is_unbound()) {
- write_light_entry(doc, lights_el, l.name, l.primary);
- }
- for (auto &alt : l.alternatives) {
- if (!alt.is_unbound()) {
- write_light_entry(doc, lights_el, l.name, alt);
+ if (save_lights) {
+ for (auto &l : tmpl.lights) {
+ if (!l.primary.is_unbound()) {
+ write_light_entry(doc, lights_el, l.name, l.primary);
+ }
+ for (auto &alt : l.alternatives) {
+ if (!alt.is_unbound()) {
+ write_light_entry(doc, lights_el, l.name, alt);
+ }
}
}
}
@@ -424,12 +440,14 @@ namespace overlay::windows {
std::vector get_templates_for_game(const std::string &game_name) {
std::vector result;
+ log_misc("templates", "loading built-in templates for {}", game_name);
for (auto &t : load_builtin_templates()) {
if (t.game_name == game_name) {
result.push_back(std::move(t));
}
}
+ log_misc("templates", "loading user templates for {}", game_name);
for (auto &t : load_user_templates()) {
if (t.game_name == game_name) {
result.push_back(std::move(t));
diff --git a/src/spice2x/overlay/windows/config.cpp b/src/spice2x/overlay/windows/config.cpp
index fe4e353..006abda 100644
--- a/src/spice2x/overlay/windows/config.cpp
+++ b/src/spice2x/overlay/windows/config.cpp
@@ -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(this->tab_selected),
+ static_cast(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 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();
diff --git a/src/spice2x/overlay/windows/config.h b/src/spice2x/overlay/windows/config.h
index f7ef64c..509f8aa 100644
--- a/src/spice2x/overlay/windows/config.h
+++ b/src/spice2x/overlay/windows/config.h
@@ -110,6 +110,16 @@ namespace overlay::windows {
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;
diff --git a/src/spice2x/overlay/windows/controller_presets.cpp b/src/spice2x/overlay/windows/controller_presets.cpp
index acf0eb8..8a33499 100644
--- a/src/spice2x/overlay/windows/controller_presets.cpp
+++ b/src/spice2x/overlay/windows/controller_presets.cpp
@@ -96,7 +96,9 @@ namespace overlay::windows {
collect_sources_from(buttons, sources_set, has_naive);
collect_sources_from(keypad_buttons, sources_set, has_naive);
for (auto &a : analogs) {
- if (a.is_device()) sources_set.insert(a.device_identifier);
+ if (a.is_device()) {
+ sources_set.insert(a.device_identifier);
+ }
}
for (auto &l : lights) {
if (l.primary.is_device()) sources_set.insert(l.primary.device_identifier);
diff --git a/src/spice2x/overlay/windows/controller_presets.h b/src/spice2x/overlay/windows/controller_presets.h
index 17b891a..c5f0d55 100644
--- a/src/spice2x/overlay/windows/controller_presets.h
+++ b/src/spice2x/overlay/windows/controller_presets.h
@@ -145,7 +145,13 @@ namespace overlay::windows {
// template management API
std::vector get_templates_for_game(const std::string &game_name);
std::vector load_user_templates();
- bool save_user_template(const ControllerTemplate &tmpl);
+ bool save_user_template(
+ const ControllerTemplate &tmpl,
+ const bool save_buttons,
+ const bool save_keypads,
+ const bool save_analogs,
+ const bool save_lights);
+
bool delete_user_template(const std::string &game_name, const std::string &template_name);
bool rename_user_template(const std::string &game_name,
const std::string &old_name, const std::string &new_name);