mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
overlay: remove multiple pages from Buttons/Overlay/Lights tabs, replace with tree layout (#541)
The old pages UI was not intuitive and often led to questions like: * How do I bind multiple controllers to a single input?? (failure to discover) * I have a ghost input that won't go away, how do I fix this? Is this a bug? (non-intuitive UI - there are too many pages and finding out where each binding is potentially requires scrolling through 100 pages) * Potential perf issue - user binds too many by accident, or puts bindings all the way in page 99, requiring us to walk each element in the vector, wasting precious CPU cycles during an input poll. This PR removes the multiple pages, and puts everything on a single page, showing multiple binds in a tree structure. It also puts a hard limit on how many alternate bindings can be made (8 for buttons, 16 for lights), though if the user has configured more in older version they will be respected.
This commit is contained in:
@@ -45,6 +45,7 @@ private:
|
|||||||
double debounce_up = 0.0;
|
double debounce_up = 0.0;
|
||||||
double debounce_down = 0.0;
|
double debounce_down = 0.0;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
|
bool is_temporary = false;
|
||||||
|
|
||||||
GameAPI::Buttons::State last_state = GameAPI::Buttons::BUTTON_NOT_PRESSED;
|
GameAPI::Buttons::State last_state = GameAPI::Buttons::BUTTON_NOT_PRESSED;
|
||||||
float last_velocity = 0.f;
|
float last_velocity = 0.f;
|
||||||
@@ -164,6 +165,14 @@ public:
|
|||||||
this->last_velocity = last_velocity;
|
this->last_velocity = last_velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isTemporary() const {
|
||||||
|
return this->is_temporary;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setTemporary(bool is_temporary) {
|
||||||
|
this->is_temporary = is_temporary;
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned short getVelocityThreshold() const {
|
inline unsigned short getVelocityThreshold() const {
|
||||||
return this->velocity_threshold;
|
return this->velocity_threshold;
|
||||||
}
|
}
|
||||||
@@ -172,6 +181,20 @@ public:
|
|||||||
this->velocity_threshold = velocity_threshold;
|
this->velocity_threshold = velocity_threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isValid() {
|
||||||
|
// temporarily created by UI
|
||||||
|
if (isTemporary()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing is set
|
||||||
|
if (getDeviceIdentifier().empty() && getVKey() == INVALID_VKEY) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void getMidiVKey(int& channel, int& index);
|
void getMidiVKey(int& channel, int& index);
|
||||||
void setMidiVKey(rawinput::RawInputManager* manager, bool is_note, int channel, int index);
|
void setMidiVKey(rawinput::RawInputManager* manager, bool is_note, int channel, int index);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ private:
|
|||||||
std::string lightName;
|
std::string lightName;
|
||||||
std::string deviceIdentifier = "";
|
std::string deviceIdentifier = "";
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
|
bool is_temporary = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
float last_state = 0.f;
|
float last_state = 0.f;
|
||||||
@@ -65,4 +66,26 @@ public:
|
|||||||
inline void setIndex(unsigned int index) {
|
inline void setIndex(unsigned int index) {
|
||||||
this->index = index;
|
this->index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isTemporary() const {
|
||||||
|
return this->is_temporary;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setTemporary(bool is_temporary) {
|
||||||
|
this->is_temporary = is_temporary;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isValid() {
|
||||||
|
// temporarily created by UI
|
||||||
|
if (isTemporary()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing is set
|
||||||
|
if (getDeviceIdentifier().empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -257,6 +257,10 @@ namespace overlay::windows {
|
|||||||
ImGui::TextUnformatted("");
|
ImGui::TextUnformatted("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// before calling into build_buttons for game/keypads, reset this so that it can
|
||||||
|
// be recalculated
|
||||||
|
io_has_valid_alternatives = false;
|
||||||
|
|
||||||
// game buttons
|
// game buttons
|
||||||
this->build_buttons("Game", games::get_buttons(this->games_selected_name));
|
this->build_buttons("Game", games::get_buttons(this->games_selected_name));
|
||||||
|
|
||||||
@@ -285,17 +289,18 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
// page selector
|
// multi bind
|
||||||
this->build_page_selector(&this->buttons_page);
|
bind_multiple_checkbox();
|
||||||
|
|
||||||
// bind many
|
// bind many
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Checkbox("Bind Many", &buttons_many_active)) {
|
if (ImGui::Checkbox("Sequential Binding", &buttons_many_active)) {
|
||||||
buttons_many_index = -1;
|
buttons_many_index = -1;
|
||||||
buttons_many_delay = 0;
|
buttons_many_delay = 0;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::HelpTooltip("Immediately query for the next button after binding one.");
|
ImGui::HelpTooltip(
|
||||||
|
"Bind many keys in a row without having to click on Bind or Naive button.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
@@ -323,12 +328,14 @@ namespace overlay::windows {
|
|||||||
ImGui::BeginChild("Overlay", ImVec2(
|
ImGui::BeginChild("Overlay", ImVec2(
|
||||||
0, ImGui::GetWindowContentRegionMax().y - page_offset), false);
|
0, ImGui::GetWindowContentRegionMax().y - page_offset), false);
|
||||||
|
|
||||||
|
io_has_valid_alternatives = false;
|
||||||
|
|
||||||
// overlay buttons
|
// overlay buttons
|
||||||
this->build_buttons("Overlay", games::get_buttons_overlay(this->games_selected_name));
|
this->build_buttons("Overlay", games::get_buttons_overlay(this->games_selected_name));
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
// page selector
|
// multi bind
|
||||||
this->build_page_selector(&this->buttons_page);
|
bind_multiple_checkbox();
|
||||||
|
|
||||||
// standalone configurator extras
|
// standalone configurator extras
|
||||||
if (cfg::CONFIGURATOR_STANDALONE) {
|
if (cfg::CONFIGURATOR_STANDALONE) {
|
||||||
@@ -339,11 +346,16 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
if (ImGui::BeginTabItem("Lights")) {
|
if (ImGui::BeginTabItem("Lights")) {
|
||||||
tab_selected_new = ConfigTab::CONFIG_TAB_LIGHTS;
|
tab_selected_new = ConfigTab::CONFIG_TAB_LIGHTS;
|
||||||
|
|
||||||
ImGui::BeginChild("Lights", ImVec2(
|
ImGui::BeginChild("Lights", ImVec2(
|
||||||
0, ImGui::GetWindowContentRegionMax().y - page_offset), false);
|
0, ImGui::GetWindowContentRegionMax().y - page_offset), false);
|
||||||
|
io_has_valid_alternatives = false;
|
||||||
this->build_lights("Game", games::get_lights(this->games_selected_name));
|
this->build_lights("Game", games::get_lights(this->games_selected_name));
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
this->build_page_selector(&this->lights_page);
|
|
||||||
|
// multi bind
|
||||||
|
bind_multiple_checkbox();
|
||||||
|
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
}
|
}
|
||||||
if (ImGui::BeginTabItem("Cards")) {
|
if (ImGui::BeginTabItem("Cards")) {
|
||||||
@@ -561,10 +573,9 @@ namespace overlay::windows {
|
|||||||
// did tab selection change?
|
// did tab selection change?
|
||||||
if (this->tab_selected != tab_selected_new) {
|
if (this->tab_selected != tab_selected_new) {
|
||||||
this->tab_selected = tab_selected_new;
|
this->tab_selected = tab_selected_new;
|
||||||
this->buttons_page = 0;
|
|
||||||
this->lights_page = 0;
|
|
||||||
buttons_many_active = false;
|
buttons_many_active = false;
|
||||||
buttons_many_index = -1;
|
buttons_many_index = -1;
|
||||||
|
io_allow_multi_binding = false;
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,7 +596,7 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "%s Buttons", name.c_str());
|
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "%s Buttons", name.c_str());
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::BeginTable("ButtonsTable", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
|
if (ImGui::BeginTable("ButtonsTable", 3, ImGuiTableFlags_Resizable)) {
|
||||||
// longest column is probably "Toggle Virtual Keypad P1" in Overlay tab
|
// longest column is probably "Toggle Virtual Keypad P1" in Overlay tab
|
||||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, overlay::apply_scaling(220));
|
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, overlay::apply_scaling(220));
|
||||||
ImGui::TableSetupColumn("Binding", ImGuiTableColumnFlags_WidthStretch);
|
ImGui::TableSetupColumn("Binding", ImGuiTableColumnFlags_WidthStretch);
|
||||||
@@ -608,7 +619,21 @@ namespace overlay::windows {
|
|||||||
if (buttons) {
|
if (buttons) {
|
||||||
const 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++) {
|
for (int button_it = min; button_it <= button_it_max; button_it++) {
|
||||||
build_button(name, &buttons->at(button_it), button_it, button_it_max);
|
|
||||||
|
Button &primary_button = buttons->at(button_it);
|
||||||
|
|
||||||
|
// primary
|
||||||
|
build_button(name, primary_button, &primary_button, button_it, button_it_max, 0);
|
||||||
|
|
||||||
|
// alternatives
|
||||||
|
int alt_index = 1; // 0 is primary
|
||||||
|
for (auto &alt : primary_button.getAlternatives()) {
|
||||||
|
if (alt.isValid()) {
|
||||||
|
build_button(name, primary_button, &alt, button_it, button_it_max, alt_index);
|
||||||
|
io_has_valid_alternatives = true;
|
||||||
|
}
|
||||||
|
alt_index++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,35 +641,83 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::build_button(const std::string &name, Button *button, const int button_it, const int button_it_max) {
|
void Config::build_button(
|
||||||
// get button based on page
|
const std::string &name,
|
||||||
auto &button_alternatives = button->getAlternatives();
|
Button &primary_button,
|
||||||
if (this->buttons_page > 0) {
|
Button *button,
|
||||||
while ((int) button_alternatives.size() < this->buttons_page) {
|
const int button_it,
|
||||||
button_alternatives.emplace_back(button->getName());
|
const int button_it_max,
|
||||||
}
|
const int alt_index) {
|
||||||
button = &button_alternatives.at(this->buttons_page - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
|
set_alternating_row_colors(button_it);
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
// get button info
|
// get button info
|
||||||
ImGui::PushID(button);
|
ImGui::PushID(button);
|
||||||
const auto button_name = button->getName();
|
const auto button_name = button->getName();
|
||||||
const auto button_display = button->getDisplayString(RI_MGR.get());
|
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);
|
const auto button_velocity = GameAPI::Buttons::getVelocity(RI_MGR, *button);
|
||||||
|
|
||||||
// list entry
|
// list entry
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
|
const bool primary_button_state = GameAPI::Buttons::getState(RI_MGR, primary_button);
|
||||||
|
const bool button_state = GameAPI::Buttons::getState(RI_MGR, *button, false);
|
||||||
|
|
||||||
ImGui::Indent(INDENT);
|
ImGui::Indent(INDENT);
|
||||||
if (button_state) {
|
if (alt_index == 0) {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, TEXT_COLOR_GREEN);
|
// primary button
|
||||||
}
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::TextTruncated(button_name, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
if (primary_button_state) {
|
||||||
if (button_state) {
|
ImGui::PushStyleColor(ImGuiCol_Text, TEXT_COLOR_GREEN);
|
||||||
ImGui::PopStyleColor();
|
}
|
||||||
|
ImGui::TextTruncated(
|
||||||
|
button_name, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
||||||
|
if (primary_button_state) {
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (io_allow_multi_binding) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::AddButton(
|
||||||
|
"Add an alternate binding for this button. "
|
||||||
|
"All of the key bindings are OR'd together.")) {
|
||||||
|
bool available = false;
|
||||||
|
// try to find one in the list that is not bound
|
||||||
|
for (auto &alt : primary_button.getAlternatives()) {
|
||||||
|
if (!alt.isValid()) {
|
||||||
|
alt.setTemporary(true);
|
||||||
|
available = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// old pages UI allowed 99 alternatives, which is a little excessive
|
||||||
|
// here, limit to 8 (1 + 7 alts) here as a reasonable upper bound
|
||||||
|
if (!available && primary_button.getAlternatives().size() < 7) {
|
||||||
|
// add a new one to end of the list
|
||||||
|
Button temp_button(button->getName());
|
||||||
|
temp_button.setTemporary(true);
|
||||||
|
button->getAlternatives().push_back(temp_button);
|
||||||
|
::Config::getInstance().updateBinding(
|
||||||
|
games_list[games_selected], temp_button,
|
||||||
|
button->getAlternatives().size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// alternate button
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
if (button_state) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, TEXT_COLOR_GREEN);
|
||||||
|
}
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::TextTruncated(
|
||||||
|
fmt::format("\u00B7 alternate #{}", alt_index),
|
||||||
|
ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
if (button_state) {
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::Unindent(INDENT);
|
ImGui::Unindent(INDENT);
|
||||||
|
|
||||||
@@ -654,17 +727,23 @@ namespace overlay::windows {
|
|||||||
if (button_state) {
|
if (button_state) {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, TEXT_COLOR_GREEN);
|
ImGui::PushStyleColor(ImGuiCol_Text, TEXT_COLOR_GREEN);
|
||||||
}
|
}
|
||||||
ImGui::TextTruncated(
|
if (alt_index > 0) {
|
||||||
button_display, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::TextTruncated(
|
||||||
|
"\u00B7 " + button_display, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
} else {
|
||||||
|
ImGui::TextTruncated(
|
||||||
|
button_display, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
||||||
|
}
|
||||||
if (button_state) {
|
if (button_state) {
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear button
|
// clear button
|
||||||
if (button_display.size() > 0) {
|
if (button_display.size() > 0 || alt_index > 0) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::DeleteButton("Unbind")) {
|
if (ImGui::DeleteButton(button_display.size() > 0 ? "Unbind" : "Delete")) {
|
||||||
clear_button(button);
|
clear_button(button, alt_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,8 +754,9 @@ namespace overlay::windows {
|
|||||||
std::string bind_name = "Bind " + button_name;
|
std::string bind_name = "Bind " + button_name;
|
||||||
if (ImGui::Button("Bind")
|
if (ImGui::Button("Bind")
|
||||||
|| (buttons_many_active && buttons_many_active_section == name && !buttons_bind_active
|
|| (buttons_many_active && buttons_many_active_section == name && !buttons_bind_active
|
||||||
&& !buttons_many_naive && buttons_many_index == button_it
|
&& alt_index == 0
|
||||||
&& ++buttons_many_delay > 25)) {
|
&& !buttons_many_naive && buttons_many_index == button_it
|
||||||
|
&& ++buttons_many_delay > 25)) {
|
||||||
ImGui::OpenPopup(bind_name.c_str());
|
ImGui::OpenPopup(bind_name.c_str());
|
||||||
buttons_bind_active = true;
|
buttons_bind_active = true;
|
||||||
if (buttons_many_active) {
|
if (buttons_many_active) {
|
||||||
@@ -727,15 +807,16 @@ namespace overlay::windows {
|
|||||||
ImGui::HelpTooltip("Bind a button to a device using Windows RawInput API.");
|
ImGui::HelpTooltip("Bind a button to a device using Windows RawInput API.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bind_button_popup(bind_name, button, button_it_max);
|
bind_button_popup(bind_name, button, button_it_max, alt_index);
|
||||||
|
|
||||||
// naive binding
|
// naive binding
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
std::string naive_string = "Naive " + button_name;
|
std::string naive_string = "Naive " + button_name;
|
||||||
if (ImGui::Button("Naive")
|
if (ImGui::Button("Naive")
|
||||||
|| (buttons_many_active && buttons_many_active_section == name && !buttons_bind_active
|
|| (buttons_many_active && buttons_many_active_section == name && !buttons_bind_active
|
||||||
&& buttons_many_naive && buttons_many_index == button_it
|
&& alt_index == 0
|
||||||
&& ++buttons_many_delay > 25)) {
|
&& buttons_many_naive && buttons_many_index == button_it
|
||||||
|
&& ++buttons_many_delay > 25)) {
|
||||||
ImGui::OpenPopup(naive_string.c_str());
|
ImGui::OpenPopup(naive_string.c_str());
|
||||||
if (buttons_many_active) {
|
if (buttons_many_active) {
|
||||||
buttons_many_index = button_it;
|
buttons_many_index = button_it;
|
||||||
@@ -758,21 +839,26 @@ namespace overlay::windows {
|
|||||||
" * if you have NKRO issues with Bind");
|
" * if you have NKRO issues with Bind");
|
||||||
}
|
}
|
||||||
|
|
||||||
naive_button_popup(naive_string, button, button_it_max);
|
naive_button_popup(naive_string, button, button_it_max, alt_index);
|
||||||
|
|
||||||
// edit button
|
// edit button
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
std::string edit_name = "Edit " + button->getName();
|
std::string edit_name = "Edit " + button->getName();
|
||||||
|
if (alt_index > 0) {
|
||||||
|
edit_name += " (alternate #" + std::to_string(alt_index) + ")";
|
||||||
|
} else {
|
||||||
|
edit_name += " (primary)";
|
||||||
|
}
|
||||||
if (ImGui::Button("Edit")) {
|
if (ImGui::Button("Edit")) {
|
||||||
ImGui::OpenPopup(edit_name.c_str());
|
ImGui::OpenPopup(edit_name.c_str());
|
||||||
}
|
}
|
||||||
edit_button_popup(edit_name, button_display, button, button_state, button_velocity);
|
edit_button_popup(edit_name, button_display, button, button_velocity, alt_index);
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::clear_button(Button *button) {
|
void Config::clear_button(Button *button, const int alt_index) {
|
||||||
button->setDeviceIdentifier("");
|
button->setDeviceIdentifier("");
|
||||||
button->setVKey(0xFF);
|
button->setVKey(0xFF);
|
||||||
button->setAnalogType(BAT_NONE);
|
button->setAnalogType(BAT_NONE);
|
||||||
@@ -782,12 +868,31 @@ namespace overlay::windows {
|
|||||||
button->setInvert(false);
|
button->setInvert(false);
|
||||||
button->setLastState(GameAPI::Buttons::BUTTON_NOT_PRESSED);
|
button->setLastState(GameAPI::Buttons::BUTTON_NOT_PRESSED);
|
||||||
button->setLastVelocity(0);
|
button->setLastVelocity(0);
|
||||||
|
button->setTemporary(false);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::bind_button_popup(const std::string &bind_name, Button *button, const int button_it_max) {
|
void Config::bind_multiple_checkbox() {
|
||||||
|
ImGui::BeginDisabled(io_has_valid_alternatives);
|
||||||
|
if (io_has_valid_alternatives) {
|
||||||
|
io_allow_multi_binding = true;
|
||||||
|
}
|
||||||
|
ImGui::Checkbox("Allow Multiple Binds", &io_allow_multi_binding);
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||||
|
std::string text =
|
||||||
|
"Check this and press the green + button to bind multiple input to the same action.";
|
||||||
|
if (io_has_valid_alternatives) {
|
||||||
|
text += "\n\n(You already have multiple bindings, so this is enabled)";
|
||||||
|
}
|
||||||
|
ImGui::HelpTooltip(text.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Config::bind_button_popup(
|
||||||
|
const std::string &bind_name, Button *button, const int button_it_max, const int alt_index) {
|
||||||
|
|
||||||
if (ImGui::BeginPopupModal(bind_name.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
if (ImGui::BeginPopupModal(bind_name.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
|
|
||||||
@@ -824,7 +929,7 @@ namespace overlay::windows {
|
|||||||
button->setVKey(static_cast<unsigned short>(i));
|
button->setVKey(static_cast<unsigned short>(i));
|
||||||
button->setAnalogType(BAT_NONE);
|
button->setAnalogType(BAT_NONE);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button, buttons_page - 1);
|
games_list[games_selected], *button, alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -855,7 +960,7 @@ namespace overlay::windows {
|
|||||||
button->setVKey(vkey);
|
button->setVKey(vkey);
|
||||||
button->setAnalogType(BAT_NONE);
|
button->setAnalogType(BAT_NONE);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button, buttons_page - 1);
|
games_list[games_selected], *button, alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -888,7 +993,7 @@ namespace overlay::windows {
|
|||||||
button->setAnalogType(BAT_NONE);
|
button->setAnalogType(BAT_NONE);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -931,7 +1036,7 @@ namespace overlay::windows {
|
|||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -963,7 +1068,7 @@ namespace overlay::windows {
|
|||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -1012,7 +1117,7 @@ namespace overlay::windows {
|
|||||||
device->midiInfo->v2_velocity_threshold[button->getVKey()]);
|
device->midiInfo->v2_velocity_threshold[button->getVKey()]);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -1035,7 +1140,7 @@ namespace overlay::windows {
|
|||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -1061,7 +1166,7 @@ namespace overlay::windows {
|
|||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -1087,7 +1192,7 @@ namespace overlay::windows {
|
|||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -1112,7 +1217,7 @@ namespace overlay::windows {
|
|||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -1132,7 +1237,7 @@ namespace overlay::windows {
|
|||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -1161,7 +1266,7 @@ namespace overlay::windows {
|
|||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
buttons_bind_active = false;
|
buttons_bind_active = false;
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
@@ -1183,7 +1288,8 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::naive_button_popup(const std::string &naive_string, Button *button, const int button_it_max) {
|
void Config::naive_button_popup(
|
||||||
|
const std::string &naive_string, Button *button, const int button_it_max, const int alt_index) {
|
||||||
if (ImGui::BeginPopupModal(naive_string.c_str(), NULL,
|
if (ImGui::BeginPopupModal(naive_string.c_str(), NULL,
|
||||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
buttons_bind_active = true;
|
buttons_bind_active = true;
|
||||||
@@ -1252,7 +1358,7 @@ namespace overlay::windows {
|
|||||||
button->setVelocityThreshold(0);
|
button->setVelocityThreshold(0);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button,
|
games_list[games_selected], *button,
|
||||||
buttons_page - 1);
|
alt_index - 1);
|
||||||
inc_buttons_many_index(button_it_max);
|
inc_buttons_many_index(button_it_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1272,9 +1378,10 @@ namespace overlay::windows {
|
|||||||
const std::string &edit_name,
|
const std::string &edit_name,
|
||||||
const std::string &button_display,
|
const std::string &button_display,
|
||||||
Button *button,
|
Button *button,
|
||||||
const GameAPI::Buttons::State button_state,
|
const float button_velocity,
|
||||||
const float button_velocity) {
|
const int alt_index) {
|
||||||
|
|
||||||
|
const auto button_state = GameAPI::Buttons::getState(RI_MGR, *button, false);
|
||||||
if (ImGui::BeginPopupModal(edit_name.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
if (ImGui::BeginPopupModal(edit_name.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
auto device = RI_MGR->devices_get(button->getDeviceIdentifier());
|
auto device = RI_MGR->devices_get(button->getDeviceIdentifier());
|
||||||
@@ -1696,7 +1803,7 @@ namespace overlay::windows {
|
|||||||
// check if dirty
|
// check if dirty
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *button, buttons_page - 1);
|
games_list[games_selected], *button, alt_index - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// close button
|
// close button
|
||||||
@@ -2162,7 +2269,7 @@ namespace overlay::windows {
|
|||||||
void Config::build_lights(const std::string &name, std::vector<Light> *lights) {
|
void Config::build_lights(const std::string &name, std::vector<Light> *lights) {
|
||||||
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Lights");
|
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Lights");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::BeginTable("LightsTable", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
|
if (ImGui::BeginTable("LightsTable", 3, ImGuiTableFlags_Resizable)) {
|
||||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
|
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
|
||||||
ImGui::TableSetupColumn("Binding", ImGuiTableColumnFlags_WidthStretch);
|
ImGui::TableSetupColumn("Binding", ImGuiTableColumnFlags_WidthStretch);
|
||||||
ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, overlay::apply_scaling(100));
|
ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, overlay::apply_scaling(100));
|
||||||
@@ -2182,8 +2289,23 @@ namespace overlay::windows {
|
|||||||
|
|
||||||
// check lights
|
// check lights
|
||||||
if (lights) {
|
if (lights) {
|
||||||
for (auto &light_in : *lights) {
|
int light_index = 0;
|
||||||
build_light(&light_in);
|
for (auto &light : *lights) {
|
||||||
|
// primary
|
||||||
|
build_light(light, &light, light_index, 0);
|
||||||
|
|
||||||
|
// alternatives
|
||||||
|
int alt_index = 1; // 0 is primary
|
||||||
|
for (auto &alt : light.getAlternatives()) {
|
||||||
|
if (alt.isValid()) {
|
||||||
|
build_light(light, &alt, light_index, alt_index);
|
||||||
|
io_has_valid_alternatives = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
alt_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
light_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2191,42 +2313,79 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::build_light(Light *light) {
|
void Config::build_light(
|
||||||
// get light based on page
|
Light &primary_light, Light *light, const int light_index, const int alt_index) {
|
||||||
auto &light_alternatives = light->getAlternatives();
|
|
||||||
if (this->lights_page > 0) {
|
|
||||||
while ((int) light_alternatives.size() < this->lights_page) {
|
|
||||||
light_alternatives.emplace_back(light->getName());
|
|
||||||
}
|
|
||||||
light = &light_alternatives.at(this->lights_page - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get light info
|
// get light info
|
||||||
auto light_name = light->getName();
|
auto light_name = light->getName();
|
||||||
auto light_display = light->getDisplayString(RI_MGR.get());
|
auto light_display = light->getDisplayString(RI_MGR.get());
|
||||||
auto light_state = GameAPI::Lights::readLight(RI_MGR, *light);
|
auto light_state = GameAPI::Lights::readLight(RI_MGR, primary_light);
|
||||||
|
|
||||||
// list entry
|
// list entry
|
||||||
ImGui::PushID(light);
|
ImGui::PushID(light);
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
|
set_alternating_row_colors(light_index);
|
||||||
|
|
||||||
// progress bar & light name
|
// progress bar
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::ProgressBar(light_state, ImVec2(32.f, 0));
|
|
||||||
ImGui::SameLine();
|
// light name
|
||||||
ImGui::TextTruncated(light_name, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
if (alt_index == 0) {
|
||||||
|
ImGui::ProgressBar(light_state, ImVec2(32.f, 0));
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
ImGui::TextTruncated(
|
||||||
|
light_name, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
||||||
|
if (io_allow_multi_binding) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::AddButton("Add additional output for this light.")) {
|
||||||
|
bool available = false;
|
||||||
|
// try to find one in the list that is not bound
|
||||||
|
for (auto &alt : primary_light.getAlternatives()) {
|
||||||
|
if (!alt.isValid()) {
|
||||||
|
alt.setTemporary(true);
|
||||||
|
available = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// old pages UI allowed 99 alternatives, which is a little excessive
|
||||||
|
// here, limit to 16 (1 + 15 alts) here as a reasonable upper bound
|
||||||
|
if (!available && primary_light.getAlternatives().size() < 7) {
|
||||||
|
// add a new one to end of the list
|
||||||
|
Light temp_light(light->getName());
|
||||||
|
temp_light.setTemporary(true);
|
||||||
|
primary_light.getAlternatives().push_back(temp_light);
|
||||||
|
::Config::getInstance().updateBinding(
|
||||||
|
games_list[games_selected], temp_light,
|
||||||
|
primary_light.getAlternatives().size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
ImGui::Dummy(ImVec2(32.f, 0));
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextDisabled("\u00B7 alternate #%d", alt_index);
|
||||||
|
}
|
||||||
|
|
||||||
// binding name
|
// binding name
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::TextTruncated(
|
if (alt_index > 0) {
|
||||||
light_display, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
ImGui::BeginDisabled(alt_index > 0);
|
||||||
|
ImGui::TextTruncated(
|
||||||
|
"\u00B7 " + light_display, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
} else {
|
||||||
|
ImGui::TextTruncated(
|
||||||
|
light_display, ImGui::GetContentRegionAvail().x - overlay::apply_scaling(20));
|
||||||
|
}
|
||||||
|
|
||||||
// clear light
|
// clear light
|
||||||
if (light_display.size() > 0) {
|
if (light_display.size() > 0 || alt_index > 0) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::DeleteButton("Remove")) {
|
if (ImGui::DeleteButton(light_display.size() > 0 ? "Unbind" : "Delete")) {
|
||||||
clear_light(light);
|
clear_light(light, alt_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2265,21 +2424,22 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
edit_light_popup(light);
|
edit_light_popup(primary_light, light, alt_index);
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::clear_light(Light *light) {
|
void Config::clear_light(Light *light, const int alt_index) {
|
||||||
light->setDeviceIdentifier("");
|
light->setDeviceIdentifier("");
|
||||||
light->setIndex(0xFF);
|
light->setIndex(0xFF);
|
||||||
|
light->setTemporary(false);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *light,
|
games_list[games_selected], *light,
|
||||||
lights_page - 1);
|
alt_index - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::edit_light_popup(Light *light) {
|
void Config::edit_light_popup(Light &primary_light, Light *light, const int alt_index) {
|
||||||
if (ImGui::BeginPopupModal("Light Binding", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
if (ImGui::BeginPopupModal("Light Binding", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
|
|
||||||
// device selector
|
// device selector
|
||||||
@@ -2398,25 +2558,25 @@ namespace overlay::windows {
|
|||||||
light->setDeviceIdentifier(identifier);
|
light->setDeviceIdentifier(identifier);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *light,
|
games_list[games_selected], *light,
|
||||||
lights_page - 1);
|
alt_index - 1);
|
||||||
}
|
}
|
||||||
if (this->lights_devices_control_selected >= 0) {
|
if (this->lights_devices_control_selected >= 0) {
|
||||||
if ((int) light->getIndex() != this->lights_devices_control_selected) {
|
if ((int) light->getIndex() != this->lights_devices_control_selected) {
|
||||||
light->setIndex(this->lights_devices_control_selected);
|
light->setIndex(this->lights_devices_control_selected);
|
||||||
::Config::getInstance().updateBinding(
|
::Config::getInstance().updateBinding(
|
||||||
games_list[games_selected], *light,
|
games_list[games_selected], *light,
|
||||||
lights_page - 1);
|
alt_index - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// value preview
|
// value preview (use primary light for this)
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
float value_orig = GameAPI::Lights::readLight(RI_MGR, *light);
|
float value_orig = GameAPI::Lights::readLight(RI_MGR, primary_light);
|
||||||
float value = value_orig;
|
float value = value_orig;
|
||||||
ImGui::SliderFloat("Preview", &value, 0.f, 1.f);
|
ImGui::SliderFloat("Preview", &value, 0.f, 1.f);
|
||||||
|
|
||||||
// manual button controls
|
// manual button controls (use primary light for this as well)
|
||||||
if (ImGui::Button("Turn On")) {
|
if (ImGui::Button("Turn On")) {
|
||||||
value = 1.f;
|
value = 1.f;
|
||||||
}
|
}
|
||||||
@@ -2428,16 +2588,15 @@ namespace overlay::windows {
|
|||||||
// manual lock
|
// manual lock
|
||||||
if (!cfg::CONFIGURATOR_STANDALONE) {
|
if (!cfg::CONFIGURATOR_STANDALONE) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Checkbox("Lock", &light->override_enabled);
|
ImGui::Checkbox("Lock", &primary_light.override_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply new value
|
// apply new value
|
||||||
if (value != value_orig || control_changed) {
|
if (value != value_orig || control_changed) {
|
||||||
if (light->override_enabled) {
|
if (primary_light.override_enabled) {
|
||||||
light->override_state = value;
|
primary_light.override_state = value;
|
||||||
}
|
}
|
||||||
auto ident = light->getDeviceIdentifier();
|
GameAPI::Lights::writeLight(RI_MGR, primary_light, value);
|
||||||
GameAPI::Lights::writeLight(RI_MGR->devices_get(ident), light->getIndex(), value);
|
|
||||||
RI_MGR->devices_flush_output();
|
RI_MGR->devices_flush_output();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2445,7 +2604,10 @@ namespace overlay::windows {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::Button("Close")) {
|
if (ImGui::Button("Close")) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
light->override_enabled = false;
|
primary_light.override_enabled = false;
|
||||||
|
for (auto &alt : primary_light.getAlternatives()) {
|
||||||
|
alt.override_enabled = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
@@ -3059,37 +3221,6 @@ namespace overlay::windows {
|
|||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::build_page_selector(int *page) {
|
|
||||||
|
|
||||||
// left page selector
|
|
||||||
if (ImGui::Button("<")) {
|
|
||||||
*page = *page - 1;
|
|
||||||
if (*page < 0) {
|
|
||||||
*page = 99;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// page display and reset
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(("Page " + to_string(*page)).c_str())) {
|
|
||||||
*page = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// right page selector
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(">")) {
|
|
||||||
*page = *page + 1;
|
|
||||||
if (*page > 99) {
|
|
||||||
*page = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// help
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::HelpMarker("You can bind buttons/lights to multiple inputs/outputs "
|
|
||||||
"at the same time using pages.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Config::launch_shell(LPCSTR app, LPCSTR file) {
|
void Config::launch_shell(LPCSTR app, LPCSTR file) {
|
||||||
// doing this on a separate thread to avoid polluting ImGui context
|
// doing this on a separate thread to avoid polluting ImGui context
|
||||||
std::thread t([app, file] {
|
std::thread t([app, file] {
|
||||||
@@ -3191,4 +3322,12 @@ namespace overlay::windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Config::set_alternating_row_colors(const int row_index) {
|
||||||
|
auto color = ImGuiCol_TableRowBg;
|
||||||
|
if (row_index % 2 != 0) {
|
||||||
|
color = ImGuiCol_TableRowBgAlt;
|
||||||
|
}
|
||||||
|
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ImGui::GetColorU32(color));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ namespace overlay::windows {
|
|||||||
ConfigTab tab_selected = ConfigTab::CONFIG_TAB_INVALID;
|
ConfigTab tab_selected = ConfigTab::CONFIG_TAB_INVALID;
|
||||||
|
|
||||||
// buttons tab
|
// buttons tab
|
||||||
int buttons_page = 0;
|
|
||||||
bool buttons_keyboard_state[0xFF];
|
bool buttons_keyboard_state[0xFF];
|
||||||
bool buttons_bind_active = false;
|
bool buttons_bind_active = false;
|
||||||
bool buttons_many_active = false;
|
bool buttons_many_active = false;
|
||||||
@@ -47,6 +46,9 @@ namespace overlay::windows {
|
|||||||
int buttons_many_delay = 0;
|
int buttons_many_delay = 0;
|
||||||
int buttons_many_index = -1;
|
int buttons_many_index = -1;
|
||||||
|
|
||||||
|
bool io_allow_multi_binding = false;
|
||||||
|
bool io_has_valid_alternatives = false;
|
||||||
|
|
||||||
void inc_buttons_many_index(int index_max);
|
void inc_buttons_many_index(int index_max);
|
||||||
|
|
||||||
// analogs tab
|
// analogs tab
|
||||||
@@ -55,7 +57,6 @@ namespace overlay::windows {
|
|||||||
int analogs_devices_control_selected = -1;
|
int analogs_devices_control_selected = -1;
|
||||||
|
|
||||||
// lights tab
|
// lights tab
|
||||||
int lights_page = 0;
|
|
||||||
std::vector<rawinput::Device *> lights_devices;
|
std::vector<rawinput::Device *> lights_devices;
|
||||||
int lights_devices_selected = -1;
|
int lights_devices_selected = -1;
|
||||||
int lights_devices_control_selected = -1;
|
int lights_devices_control_selected = -1;
|
||||||
@@ -79,24 +80,32 @@ namespace overlay::windows {
|
|||||||
std::string search_filter_in_lower_case = "";
|
std::string search_filter_in_lower_case = "";
|
||||||
|
|
||||||
void build_buttons(const std::string &name, std::vector<Button> *buttons, int min = 0, int max = -1);
|
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 build_button(
|
||||||
void bind_button_popup(const std::string &bind_name, Button *button, const int button_it_max);
|
const std::string &name,
|
||||||
void naive_button_popup(const std::string &naive_string, Button *button, const int button_it_max);
|
Button &primary_button,
|
||||||
|
Button *button,
|
||||||
|
const int button_it,
|
||||||
|
const int button_it_max,
|
||||||
|
const int alt_index);
|
||||||
|
|
||||||
|
void bind_button_popup(const std::string &bind_name, Button *button, const int button_it_max, const int alt_index);
|
||||||
|
void naive_button_popup(const std::string &naive_string, Button *button, const int button_it_max, const int alt_index);
|
||||||
void edit_button_popup(
|
void edit_button_popup(
|
||||||
const std::string &edit_name,
|
const std::string &edit_name,
|
||||||
const std::string &button_display,
|
const std::string &button_display,
|
||||||
Button *button,
|
Button *button,
|
||||||
const GameAPI::Buttons::State button_state,
|
const float button_velocity,
|
||||||
const float button_velocity);
|
const int alt_index);
|
||||||
void clear_button(Button *button);
|
void clear_button(Button *button, const int alt_index);
|
||||||
|
void bind_multiple_checkbox();
|
||||||
|
|
||||||
void build_analogs(const std::string &name, std::vector<Analog> *analogs);
|
void build_analogs(const std::string &name, std::vector<Analog> *analogs);
|
||||||
void edit_analog_popup(Analog &analog);
|
void edit_analog_popup(Analog &analog);
|
||||||
|
|
||||||
void build_lights(const std::string &name, std::vector<Light> *lights);
|
void build_lights(const std::string &name, std::vector<Light> *lights);
|
||||||
void build_light(Light *light);
|
void build_light(Light &primary_light, Light *light, const int light_index, const int alt_index);
|
||||||
void clear_light(Light *light);
|
void clear_light(Light *light, const int alt_index);
|
||||||
void edit_light_popup(Light *light);
|
void edit_light_popup(Light &primary_light, Light *light, const int alt_index);
|
||||||
|
|
||||||
void build_cards();
|
void build_cards();
|
||||||
void build_options(
|
void build_options(
|
||||||
@@ -105,10 +114,11 @@ namespace overlay::windows {
|
|||||||
void build_launcher();
|
void build_launcher();
|
||||||
void launch_shell(LPCSTR app, LPCSTR file=nullptr);
|
void launch_shell(LPCSTR app, LPCSTR file=nullptr);
|
||||||
|
|
||||||
void build_page_selector(int *page);
|
|
||||||
void build_menu(int *game_selected);
|
void build_menu(int *game_selected);
|
||||||
void shutdown_system(bool force, bool reboot_instead);
|
void shutdown_system(bool force, bool reboot_instead);
|
||||||
|
|
||||||
|
void set_alternating_row_colors(const int row_index);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Config(SpiceOverlay *overlay);
|
Config(SpiceOverlay *overlay);
|
||||||
~Config() override;
|
~Config() override;
|
||||||
|
|||||||
Reference in New Issue
Block a user