Skip to content

Commit

Permalink
Allow a button to be mapped to multiple keys
Browse files Browse the repository at this point in the history
  • Loading branch information
S-Dafarra committed Apr 5, 2024
1 parent c3505a7 commit 0589aed
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 28 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ The device can be configured using the following parameters. They are all option
- ``axes``: definition of the list of axes. The allowed values are "ws", "ad", "up_down" and "left_right". It is possible to select the default sign for an axis prepending a "+" or a "-" to the axis name. For example, "+ws" will set the "ws" axis with the default sign, while "-ws" will set the "ws" axis with the inverted sign. It is also possible to repeat some axis, and use "none" or "" to have dummy axes with always zero value. The order matters. (default: ("ad", "ws", "left_right", "up_down"))
- ``wasd_label``: label for the "WASD" widget (default: "WASD")
- ``arrows_label``: label for the "Arrows" widget (default: "Arrows")
- ``buttons``: definition of the list of buttons. The allowed values are all the letters from A to Z, all the numbers from 0 to 9, "SPACE", "ENTER", "ESCAPE", "BACKSPACE", "DELETE", "LEFT", "RIGHT", "UP", "DOWN". It is possible to repeat some button. It is possible to specify an alias after a ":". For example "A:Some Text" will create a button with the label "Some Text" that can be activated by pressing "A". It is possible to use "none" or "" to indicate a dummy button always zero. It is possible to repeat buttons. The order matters. (default: ())
- ``buttons``: definition of the list of buttons. The allowed values are all the letters from A to Z, all the numbers from 0 to 9, "SPACE", "ENTER", "ESCAPE", "BACKSPACE", "DELETE", "LEFT", "RIGHT", "UP", "DOWN". It is possible to repeat some button. It is possible to specify an alias after a ":". For example "A:Some Text" will create a button with the label "Some Text" that can be activated by pressing "A". It is possible to use "none" or "" to indicate a dummy button always zero. It is possible to spcify multiple keys using the "-" delimiter. For example, "A-B:Some Text" creates a button named "Some Text" that can be activated pressing either A or B. It is possible to repeat buttons. The order matters. (default: ())
91 changes: 64 additions & 27 deletions src/devices/keyboard-joypad/KeyboardJoypad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ struct ButtonState {
bool buttonReleased = ImGui::Button(alias.c_str(), buttonSize);
bool buttonKeptPressed = ImGui::IsItemActive();

if (buttonReleased && (toggleButton || regularButton && hold_active))
if (buttonReleased && (toggleButton || (regularButton && hold_active)))
{
active = !active; //Toggle the button
}
Expand Down Expand Up @@ -426,12 +426,12 @@ class yarp::dev::KeyboardJoypad::Impl
int col = 0;
for (size_t i = 0; i < buttons_list->size(); i++)
{
std::string button_with_alias;
std::string buttons_with_alias;
if (!buttons_list->get(i).isString())
{
if (buttons_list->get(i).isInt64() || buttons_list->get(i).isInt32())
{
button_with_alias = std::to_string(buttons_list->get(i).asInt64());
buttons_with_alias = std::to_string(buttons_list->get(i).asInt64());
}
else
{
Expand All @@ -441,31 +441,45 @@ class yarp::dev::KeyboardJoypad::Impl
}
else
{
button_with_alias = buttons_list->get(i).asString();
buttons_with_alias = buttons_list->get(i).asString();
}

if (button_with_alias == "" || button_with_alias == "none")
if (buttons_with_alias == "" || buttons_with_alias == "none")
{
continue;
}

std::string button = button_with_alias;
std::string buttons_keys = buttons_with_alias;
std::string alias = "";

size_t pos = button_with_alias.find(':');
size_t pos = buttons_with_alias.find(':');
bool have_alias = false;
if (pos != std::string::npos)
{
button = button_with_alias.substr(0, pos);
alias = button_with_alias.substr(pos + 1);
buttons_keys = buttons_with_alias.substr(0, pos);
alias = buttons_with_alias.substr(pos + 1);
have_alias = true;
}
else
{
alias = button;
alias = buttons_keys;
}

std::transform(button.begin(), button.end(), button.begin(), ::toupper);
std::transform(buttons_keys.begin(), buttons_keys.end(), buttons_keys.begin(), ::toupper);

std::vector<std::string> buttons_key_list;
std::string delimiter = "-";
pos = buttons_keys.find(delimiter);
while (pos != std::string::npos)
{
buttons_key_list.push_back(buttons_keys.substr(0, pos));
buttons_keys.erase(0, pos + delimiter.length());
pos = buttons_keys.find(delimiter);
}
buttons_key_list.push_back(buttons_keys);

ButtonState newButton;
newButton.values.push_back({ .sign = 1, .index = i });

std::unordered_map<std::string, ImGuiKey> supportedButtons = {
{"SPACE", ImGuiKey_Space},
Expand All @@ -480,27 +494,50 @@ class yarp::dev::KeyboardJoypad::Impl
{"TAB", ImGuiKey_Tab}
};


ButtonState newButton;
newButton.values.push_back({.sign = 1, .index = i});

if (button.size() == 1 && button[0] >= 'A' && button[0] <= 'Z')
{
newButton.keys.push_back(static_cast<ImGuiKey>(ImGuiKey_A + button[0] - 'A'));
}
else if (button.size() && button[0] >= '0' && button[0] <= '9')
std::string parsedButtons;
for (auto& button : buttons_key_list)
{
newButton.keys.push_back(static_cast<ImGuiKey>(ImGuiKey_0 + button[0] - '0'));
newButton.keys.push_back(static_cast<ImGuiKey>(ImGuiKey_Keypad0 + button[0] - '0'));
yError() << "Button: " << button;
bool parsed = true;
if (button.size() == 1 && button[0] >= 'A' && button[0] <= 'Z')
{
newButton.keys.push_back(static_cast<ImGuiKey>(ImGuiKey_A + button[0] - 'A'));
}
else if (button.size() && button[0] >= '0' && button[0] <= '9')
{
newButton.keys.push_back(static_cast<ImGuiKey>(ImGuiKey_0 + button[0] - '0'));
newButton.keys.push_back(static_cast<ImGuiKey>(ImGuiKey_Keypad0 + button[0] - '0'));
}
else if (supportedButtons.find(button) != supportedButtons.end())
{
newButton.keys.push_back(supportedButtons[button]);
}
else
{
parsed = false;
}

if (parsed)
{
if (!parsedButtons.empty())
{
parsedButtons += ", " + button;
}
else
{
parsedButtons = button;
}
}
}
else if (supportedButtons.find(button) != supportedButtons.end())
yError() << "Parsed buttons: " << parsedButtons;

if (!parsedButtons.empty() && have_alias)
{
newButton.keys.push_back(supportedButtons[button]);
alias += " (" + parsedButtons + ")";
}

if (!newButton.keys.empty() && have_alias)
else if (!parsedButtons.empty() && !have_alias)
{
alias += " (" + button + ")";
alias = parsedButtons;
}

if (buttons.rows.empty() || buttons.rows.back().size() == settings.buttons_per_row)
Expand Down

0 comments on commit 0589aed

Please sign in to comment.