mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
overlay: small tweaks to auto light matching (#575)
## Link to GitHub Issue or related Pull Request, if one exists #574 ## Description of change * Add binds for Nostroller * Update matching logic to ignore common device-side output names like "Button" "Light" and "LED" (e.g., `Button 1` from a device now matches on `P1 1`) * For RGB matching, in addition to `Light R` on the device also try `LightR` (Nostroller needs this) * Add a confirmation dialog for `Clear All` * Address minor bugs ## Testing Seems to work on arcin, and Nostroller. Still need to retest Faucetwo. Hopefully I didn't break Phoenixwan.
This commit is contained in:
@@ -2416,29 +2416,44 @@ namespace overlay::windows {
|
|||||||
// clear all
|
// clear all
|
||||||
ImGui::BeginDisabled(bound.empty());
|
ImGui::BeginDisabled(bound.empty());
|
||||||
if (ImGui::Button("Clear All")) {
|
if (ImGui::Button("Clear All")) {
|
||||||
if (lights_testing) {
|
ImGui::OpenPopup("Clear all light bindings");
|
||||||
if (lights_test_current >= 0 && lights_test_current < (int) bound.size()) {
|
|
||||||
auto &cur = (*lights)[bound[lights_test_current]];
|
|
||||||
GameAPI::Lights::writeLight(RI_MGR, cur, 0.f);
|
|
||||||
RI_MGR->devices_flush_output();
|
|
||||||
}
|
|
||||||
lights_testing = false;
|
|
||||||
lights_test_current = -1;
|
|
||||||
}
|
|
||||||
for (auto &light : *lights) {
|
|
||||||
if (!light.isSet()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
clear_light(&light, 0);
|
|
||||||
for (int ai = 0; ai < (int) light.getAlternatives().size(); ai++) {
|
|
||||||
clear_light(&light.getAlternatives()[ai], ai + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
if (ImGui::IsItemHovered(ImGui::TOOLTIP_FLAGS)) {
|
if (ImGui::IsItemHovered(ImGui::TOOLTIP_FLAGS)) {
|
||||||
ImGui::SetTooltip("Unbind all lights.");
|
ImGui::SetTooltip("Unbind all lights.");
|
||||||
}
|
}
|
||||||
|
if (ImGui::BeginPopupModal("Clear all light bindings", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
|
ImGui::TextUnformatted("Are you sure? This can't be undone.");
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
if (ImGui::Button("Yes")) {
|
||||||
|
if (lights_testing) {
|
||||||
|
if (lights_test_current >= 0 && lights_test_current < (int) bound.size()) {
|
||||||
|
auto &cur = (*lights)[bound[lights_test_current]];
|
||||||
|
GameAPI::Lights::writeLight(RI_MGR, cur, 0.f);
|
||||||
|
RI_MGR->devices_flush_output();
|
||||||
|
}
|
||||||
|
lights_testing = false;
|
||||||
|
lights_test_current = -1;
|
||||||
|
}
|
||||||
|
for (auto &light : *lights) {
|
||||||
|
if (!light.isSet()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
clear_light(&light, 0);
|
||||||
|
for (int ai = 0; ai < (int) light.getAlternatives().size(); ai++) {
|
||||||
|
clear_light(&light.getAlternatives()[ai], ai + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Cancel")) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
// test all
|
// test all
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -2992,186 +3007,18 @@ namespace overlay::windows {
|
|||||||
device = auto_match_devices[auto_match_device_selected];
|
device = auto_match_devices[auto_match_device_selected];
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MatchEntry {
|
|
||||||
std::string game_name;
|
|
||||||
std::string device_name;
|
|
||||||
int light_index;
|
|
||||||
int control_index;
|
|
||||||
bool soft;
|
|
||||||
};
|
|
||||||
std::vector<MatchEntry> matched;
|
std::vector<MatchEntry> matched;
|
||||||
std::vector<MatchEntry> unmatched;
|
|
||||||
|
|
||||||
for (int li = 0; li < (int) lights->size(); li++) {
|
for (int li = 0; li < (int) lights->size(); li++) {
|
||||||
matched.push_back({
|
matched.push_back({
|
||||||
(*lights)[li].getName(), "", li, -1, false
|
(*lights)[li].getName(), "", li, -1, false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<MatchEntry> unmatched;
|
||||||
std::vector<std::string> raw_names;
|
std::vector<std::string> raw_names;
|
||||||
std::string detected_controller;
|
std::string detected_controller;
|
||||||
if (has_device) {
|
if (has_device) {
|
||||||
// build output name list
|
detected_controller = match_lights(device, lights, raw_names, matched, unmatched);
|
||||||
switch (device->type) {
|
|
||||||
case rawinput::HID: {
|
|
||||||
for (auto &n : device->hidInfo->button_output_caps_names) {
|
|
||||||
raw_names.push_back(n);
|
|
||||||
}
|
|
||||||
for (auto &n : device->hidInfo->value_output_caps_names) {
|
|
||||||
raw_names.push_back(n);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case rawinput::SEXTET_OUTPUT: {
|
|
||||||
for (int i = 0; i < rawinput::SextetDevice::LIGHT_COUNT; i++) {
|
|
||||||
raw_names.emplace_back(
|
|
||||||
rawinput::SextetDevice::LIGHT_NAMES[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case rawinput::PIUIO_DEVICE: {
|
|
||||||
for (int i = 0; i < rawinput::PIUIO::PIUIO_MAX_NUM_OF_LIGHTS; i++) {
|
|
||||||
raw_names.emplace_back(
|
|
||||||
rawinput::PIUIO::LIGHT_NAMES[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case rawinput::SMX_STAGE: {
|
|
||||||
for (int i = 0; i < rawinput::SmxStageDevice::TOTAL_LIGHT_COUNT; i++) {
|
|
||||||
raw_names.push_back(
|
|
||||||
rawinput::SmxStageDevice::GetLightNameByIndex(i));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case rawinput::SMX_DEDICAB: {
|
|
||||||
for (int i = 0; i < rawinput::SmxDedicabDevice::LIGHTS_COUNT; i++) {
|
|
||||||
raw_names.push_back(
|
|
||||||
rawinput::SmxDedicabDevice::GetLightNameByIndex(i));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// match by name (hard match, case insensitive, with P1/P2 prefix fallback)
|
|
||||||
std::vector<bool> device_matched(raw_names.size(), false);
|
|
||||||
std::string player_prefix = auto_match_p2 ? "P2 " : "P1 ";
|
|
||||||
auto player_prefix_lower = strtolower(player_prefix);
|
|
||||||
for (auto &entry : matched) {
|
|
||||||
auto game_lower = strtolower(entry.game_name);
|
|
||||||
for (int ci = 0; ci < (int) raw_names.size(); ci++) {
|
|
||||||
if (device_matched[ci]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto dev_lower = strtolower(raw_names[ci]);
|
|
||||||
if (game_lower == dev_lower || game_lower == player_prefix_lower + dev_lower) {
|
|
||||||
entry.device_name = raw_names[ci];
|
|
||||||
entry.control_index = ci;
|
|
||||||
device_matched[ci] = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// soft matching
|
|
||||||
bool is_valkyrie_mode = games::sdvx::is_valkyrie_model();
|
|
||||||
static const char *RGB[] = {" R", " G", " B"};
|
|
||||||
|
|
||||||
// try to match a game light name, first as-is, then with P1/P2 prefix
|
|
||||||
auto try_match = [&](const std::string &game_target, int ci, const char *controller) -> bool {
|
|
||||||
auto target = strtolower(game_target);
|
|
||||||
auto target_player = strtolower(player_prefix + game_target);
|
|
||||||
for (auto &entry : matched) {
|
|
||||||
if (entry.control_index >= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto entry_lower = strtolower(entry.game_name);
|
|
||||||
if (entry_lower != target && entry_lower != target_player) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entry.device_name = raw_names[ci];
|
|
||||||
entry.control_index = ci;
|
|
||||||
entry.soft = true;
|
|
||||||
device_matched[ci] = true;
|
|
||||||
if (detected_controller.empty()) {
|
|
||||||
detected_controller = controller;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int ri = 0; ri < LIGHT_MATCH_MAP_COUNT; ri++) {
|
|
||||||
auto &rule = LIGHT_MATCH_MAP[ri];
|
|
||||||
if (*rule.game && this->games_selected_name != rule.game) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (rule.vid && device->hidInfo
|
|
||||||
&& (device->hidInfo->attributes.VendorID != rule.vid
|
|
||||||
|| device->hidInfo->attributes.ProductID != rule.pid)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*rule.address) {
|
|
||||||
// address mode: match device light at specific index
|
|
||||||
int ci = (int) strtol(rule.address, nullptr, 0);
|
|
||||||
if (ci >= (int) raw_names.size() || device_matched[ci]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strtolower(raw_names[ci]) != strtolower(std::string(rule.device_light))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try_match(rule.game_light, ci, rule.controller);
|
|
||||||
} else if (rule.rgb) {
|
|
||||||
// RGB mode: expand device_light + " R/G/B" + device_suffix
|
|
||||||
const char *game_base = (is_valkyrie_mode && *rule.game_light_alt)
|
|
||||||
? rule.game_light_alt : rule.game_light;
|
|
||||||
if (!*game_base) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int ci = 0; ci < (int) raw_names.size(); ci++) {
|
|
||||||
if (device_matched[ci]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto dev_lower = strtolower(raw_names[ci]);
|
|
||||||
for (int rgb = 0; rgb < 3; rgb++) {
|
|
||||||
auto expected = strtolower(
|
|
||||||
std::string(rule.device_light) + RGB[rgb] + rule.device_suffix);
|
|
||||||
if (dev_lower != expected) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try_match(std::string(game_base) + RGB[rgb], ci, rule.controller);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// name mode: direct 1:1 device_light → game_light
|
|
||||||
const char *game_base = (is_valkyrie_mode && *rule.game_light_alt)
|
|
||||||
? rule.game_light_alt : rule.game_light;
|
|
||||||
if (!*game_base) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int ci = 0; ci < (int) raw_names.size(); ci++) {
|
|
||||||
if (device_matched[ci]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (strtolower(raw_names[ci]) != strtolower(std::string(rule.device_light))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (try_match(game_base, ci, rule.controller)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// unmatched device lights
|
|
||||||
for (int ci = 0; ci < (int) raw_names.size(); ci++) {
|
|
||||||
if (!device_matched[ci] && strtolower(raw_names[ci]) != "null") {
|
|
||||||
unmatched.push_back({"", raw_names[ci], -1, ci, false});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// partition: matches first, then hard before soft
|
// partition: matches first, then hard before soft
|
||||||
@@ -3553,6 +3400,214 @@ namespace overlay::windows {
|
|||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Config::match_lights(
|
||||||
|
rawinput::Device *device,
|
||||||
|
std::vector<Light> *lights,
|
||||||
|
std::vector<std::string> &raw_names,
|
||||||
|
std::vector<MatchEntry> &matched,
|
||||||
|
std::vector<MatchEntry> &unmatched) {
|
||||||
|
|
||||||
|
std::string detected_controller;
|
||||||
|
|
||||||
|
// build output name list
|
||||||
|
switch (device->type) {
|
||||||
|
case rawinput::HID: {
|
||||||
|
for (auto &n : device->hidInfo->button_output_caps_names) {
|
||||||
|
raw_names.push_back(n);
|
||||||
|
}
|
||||||
|
for (auto &n : device->hidInfo->value_output_caps_names) {
|
||||||
|
raw_names.push_back(n);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rawinput::SEXTET_OUTPUT: {
|
||||||
|
for (int i = 0; i < rawinput::SextetDevice::LIGHT_COUNT; i++) {
|
||||||
|
raw_names.emplace_back(
|
||||||
|
rawinput::SextetDevice::LIGHT_NAMES[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rawinput::PIUIO_DEVICE: {
|
||||||
|
for (int i = 0; i < rawinput::PIUIO::PIUIO_MAX_NUM_OF_LIGHTS; i++) {
|
||||||
|
raw_names.emplace_back(
|
||||||
|
rawinput::PIUIO::LIGHT_NAMES[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rawinput::SMX_STAGE: {
|
||||||
|
for (int i = 0; i < rawinput::SmxStageDevice::TOTAL_LIGHT_COUNT; i++) {
|
||||||
|
raw_names.push_back(
|
||||||
|
rawinput::SmxStageDevice::GetLightNameByIndex(i));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rawinput::SMX_DEDICAB: {
|
||||||
|
for (int i = 0; i < rawinput::SmxDedicabDevice::LIGHTS_COUNT; i++) {
|
||||||
|
raw_names.push_back(
|
||||||
|
rawinput::SmxDedicabDevice::GetLightNameByIndex(i));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// match by name (hard match, case insensitive, with P1/P2 prefix fallback)
|
||||||
|
std::vector<bool> device_matched(raw_names.size(), false);
|
||||||
|
const std::string player_prefix = auto_match_p2 ? "p2 " : "p1 ";
|
||||||
|
|
||||||
|
for (auto &entry : matched) {
|
||||||
|
const auto game_lower = strtolower(entry.game_name);
|
||||||
|
|
||||||
|
// match on exact name
|
||||||
|
for (int ci = 0; ci < (int) raw_names.size(); ci++) {
|
||||||
|
if (device_matched[ci]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto dev_lower = strtolower(raw_names[ci]);
|
||||||
|
if (game_lower == dev_lower ||
|
||||||
|
game_lower == player_prefix + dev_lower) {
|
||||||
|
|
||||||
|
entry.device_name = raw_names[ci];
|
||||||
|
entry.control_index = ci;
|
||||||
|
device_matched[ci] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// raw device name, but stripped of a few common strings, and spaces
|
||||||
|
for (int ci = 0; ci < (int) raw_names.size(); ci++) {
|
||||||
|
if (device_matched[ci]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dev_stripped = strtolower(raw_names[ci]);;
|
||||||
|
strreplace(dev_stripped, "button", "");
|
||||||
|
strreplace(dev_stripped, "led", "");
|
||||||
|
strreplace(dev_stripped, "light", "");
|
||||||
|
strreplace(dev_stripped, " ", "");
|
||||||
|
|
||||||
|
if (game_lower == dev_stripped ||
|
||||||
|
game_lower == player_prefix + dev_stripped) {
|
||||||
|
|
||||||
|
entry.device_name = raw_names[ci];
|
||||||
|
entry.control_index = ci;
|
||||||
|
device_matched[ci] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// soft matching
|
||||||
|
const bool is_valkyrie_mode = games::sdvx::is_valkyrie_model();
|
||||||
|
static const char *RGB[] = {"R", "G", "B"};
|
||||||
|
|
||||||
|
// try to match a game light name, first as-is, then with P1/P2 prefix
|
||||||
|
auto try_match = [&](const std::string &game_target, int ci, const char *controller) -> bool {
|
||||||
|
auto target = strtolower(game_target);
|
||||||
|
auto target_player = strtolower(player_prefix + game_target);
|
||||||
|
for (auto &entry : matched) {
|
||||||
|
if (entry.control_index >= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto entry_lower = strtolower(entry.game_name);
|
||||||
|
if (entry_lower != target && entry_lower != target_player) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entry.device_name = raw_names[ci];
|
||||||
|
entry.control_index = ci;
|
||||||
|
entry.soft = true;
|
||||||
|
device_matched[ci] = true;
|
||||||
|
if (detected_controller.empty()) {
|
||||||
|
detected_controller = controller;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int ri = 0; ri < LIGHT_MATCH_MAP_COUNT; ri++) {
|
||||||
|
auto &rule = LIGHT_MATCH_MAP[ri];
|
||||||
|
if (*rule.game && this->games_selected_name != rule.game) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (rule.vid && device->hidInfo
|
||||||
|
&& (device->hidInfo->attributes.VendorID != rule.vid
|
||||||
|
|| device->hidInfo->attributes.ProductID != rule.pid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*rule.address) {
|
||||||
|
// address mode: match device light at specific index
|
||||||
|
int ci = (int) strtol(rule.address, nullptr, 0);
|
||||||
|
if (ci >= (int) raw_names.size() || device_matched[ci]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strtolower(raw_names[ci]) != strtolower(std::string(rule.device_light))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try_match(rule.game_light, ci, rule.controller);
|
||||||
|
} else if (rule.rgb) {
|
||||||
|
// RGB mode: expand device_light + " R/G/B" + device_suffix
|
||||||
|
const char *game_base = (is_valkyrie_mode && *rule.game_light_alt)
|
||||||
|
? rule.game_light_alt : rule.game_light;
|
||||||
|
if (!*game_base) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int ci = 0; ci < (int) raw_names.size(); ci++) {
|
||||||
|
if (device_matched[ci]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto dev_lower = strtolower(raw_names[ci]);
|
||||||
|
for (int rgb = 0; rgb < 3; rgb++) {
|
||||||
|
// try light name, plus space, plus R/G/B
|
||||||
|
auto expected = strtolower(
|
||||||
|
std::string(rule.device_light) + " " + RGB[rgb] + rule.device_suffix);
|
||||||
|
if (dev_lower == expected) {
|
||||||
|
try_match(std::string(game_base) + " " + RGB[rgb], ci, rule.controller);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// try light name, plus R/G/B
|
||||||
|
auto expected2 = strtolower(
|
||||||
|
std::string(rule.device_light) + RGB[rgb] + rule.device_suffix);
|
||||||
|
if (dev_lower == expected2) {
|
||||||
|
try_match(std::string(game_base) + " " + RGB[rgb], ci, rule.controller);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// name mode: direct 1:1 device_light → game_light
|
||||||
|
const char *game_base = (is_valkyrie_mode && *rule.game_light_alt)
|
||||||
|
? rule.game_light_alt : rule.game_light;
|
||||||
|
if (!*game_base) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int ci = 0; ci < (int) raw_names.size(); ci++) {
|
||||||
|
if (device_matched[ci]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strtolower(raw_names[ci]) != strtolower(std::string(rule.device_light))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (try_match(game_base, ci, rule.controller)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unmatched device lights
|
||||||
|
for (int ci = 0; ci < (int) raw_names.size(); ci++) {
|
||||||
|
if (!device_matched[ci] && strtolower(raw_names[ci]) != "null") {
|
||||||
|
unmatched.push_back({"", raw_names[ci], -1, ci, false});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return detected_controller;
|
||||||
|
}
|
||||||
|
|
||||||
void Config::build_cards() {
|
void Config::build_cards() {
|
||||||
|
|
||||||
// early quit
|
// early quit
|
||||||
|
|||||||
@@ -26,6 +26,14 @@ namespace overlay::windows {
|
|||||||
CONFIG_TAB_SEARCH,
|
CONFIG_TAB_SEARCH,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MatchEntry {
|
||||||
|
std::string game_name;
|
||||||
|
std::string device_name;
|
||||||
|
int light_index;
|
||||||
|
int control_index;
|
||||||
|
bool soft;
|
||||||
|
};
|
||||||
|
|
||||||
class Config : public Window {
|
class Config : public Window {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -129,6 +137,13 @@ namespace overlay::windows {
|
|||||||
void edit_light_popup(Light &primary_light, Light *light, const int alt_index);
|
void edit_light_popup(Light &primary_light, Light *light, const int alt_index);
|
||||||
void auto_match_lights_popup(std::vector<Light> *lights);
|
void auto_match_lights_popup(std::vector<Light> *lights);
|
||||||
|
|
||||||
|
std::string match_lights(
|
||||||
|
rawinput::Device *device,
|
||||||
|
std::vector<Light> *lights,
|
||||||
|
std::vector<std::string> &raw_names,
|
||||||
|
std::vector<MatchEntry> &matched,
|
||||||
|
std::vector<MatchEntry> &unmatched);
|
||||||
|
|
||||||
void build_cards();
|
void build_cards();
|
||||||
std::string build_option_value_picker_title(const OptionDefinition& option);
|
std::string build_option_value_picker_title(const OptionDefinition& option);
|
||||||
void build_option_value_picker(Option& option);
|
void build_option_value_picker(Option& option);
|
||||||
|
|||||||
@@ -40,6 +40,40 @@ namespace overlay::windows {
|
|||||||
{"PHOENIXWAN", "Beatmania IIDX", 0x034C, 0x0368, "Generic Indicator", "", "0x04", false, "5", ""},
|
{"PHOENIXWAN", "Beatmania IIDX", 0x034C, 0x0368, "Generic Indicator", "", "0x04", false, "5", ""},
|
||||||
{"PHOENIXWAN", "Beatmania IIDX", 0x034C, 0x0368, "Generic Indicator", "", "0x05", false, "6", ""},
|
{"PHOENIXWAN", "Beatmania IIDX", 0x034C, 0x0368, "Generic Indicator", "", "0x05", false, "6", ""},
|
||||||
{"PHOENIXWAN", "Beatmania IIDX", 0x034C, 0x0368, "Generic Indicator", "", "0x06", false, "7", ""},
|
{"PHOENIXWAN", "Beatmania IIDX", 0x034C, 0x0368, "Generic Indicator", "", "0x06", false, "7", ""},
|
||||||
|
|
||||||
|
// Nostroller VID_0E8F&PID_1212&MI_03 (Lights 01-14) (RGB)
|
||||||
|
// The lights are named "LED_01R" "LED_01G" "LED_01B" and so on.
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_01", "", "", true, "Key 1", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_02", "", "", true, "Key 2", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_03", "", "", true, "Key 3", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_04", "", "", true, "Key 4", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_05", "", "", true, "Key 5", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_06", "", "", true, "Key 6", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_07", "", "", true, "Key 7", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_08", "", "", true, "Key 8", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_09", "", "", true, "Key 9", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_10", "", "", true, "Key 10", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_11", "", "", true, "Key 11", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_12", "", "", true, "Key 12", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_13", "", "", true, "Key 13", ""},
|
||||||
|
{"Nostroller (Lights 01-14)", "Nostalgia", 0, 0, "LED_14", "", "", true, "Key 14", ""},
|
||||||
|
|
||||||
|
// Nostroller VID_0E8F&PID_1212&MI_02 (Lights 15-28) (RGB)
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_15", "", "", true, "Key 15", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_16", "", "", true, "Key 16", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_17", "", "", true, "Key 17", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_18", "", "", true, "Key 18", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_19", "", "", true, "Key 19", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_20", "", "", true, "Key 20", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_21", "", "", true, "Key 21", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_22", "", "", true, "Key 22", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_23", "", "", true, "Key 23", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_24", "", "", true, "Key 24", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_25", "", "", true, "Key 25", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_26", "", "", true, "Key 26", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_27", "", "", true, "Key 27", ""},
|
||||||
|
{"Nostroller (Lights 15-28)", "Nostalgia", 0, 0, "LED_28", "", "", true, "Key 28", ""},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int LIGHT_MATCH_MAP_COUNT =
|
static const int LIGHT_MATCH_MAP_COUNT =
|
||||||
|
|||||||
Reference in New Issue
Block a user