16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 03:09:18 +02:00

Improve the keymapper

The keymapper, available as one of the options in the starting menu when the EXE is run without a scenery specified, has undergone a few changes:
- Key descriptions are now parsed the way Starter does and are displayed in the window. They are also no longer consumed when saving to a file.
- Unbound keys are now also displayed as well. Not all of them though; some entries won't exist if they are not specified in the eu07_input-keyboard.ini file.
- You can now unbind a key by pressing F10.

The Parser has got a new boolean option: `skipComments`, true by default to leave current behavior unchanged. When set to false, comments will be parsed as ordinary tokens.
This commit is contained in:
jakubg1
2024-03-03 03:00:47 +01:00
parent 9259708d4c
commit 84980a4484
7 changed files with 222 additions and 183 deletions

View File

@@ -122,6 +122,7 @@ bool
keyboard_input::recall_bindings() {
cParser bindingparser( "eu07_input-keyboard.ini", cParser::buffer_FILE );
bindingparser.skipComments = false;
if( false == bindingparser.ok() ) {
return false;
}
@@ -147,6 +148,7 @@ keyboard_input::recall_bindings() {
std::string bindingentry;
bindingparser >> bindingentry;
cParser entryparser( bindingentry );
entryparser.skipComments = false;
if( true == entryparser.getTokens( 1, true, "\n\r\t " ) ) {
std::string commandname;
@@ -158,32 +160,48 @@ keyboard_input::recall_bindings() {
WriteLog( "Keyboard binding defined for unknown command, \"" + commandname + "\"" );
}
else {
int binding{ 0 };
int keycode = 0;
std::string description = "";
bool descriptionStarted = false;
while( entryparser.getTokens( 1, true, "\n\r\t " ) ) {
std::string bindingkeyname;
entryparser >> bindingkeyname;
if( bindingkeyname == "shift" ) { binding |= keymodifier::shift; }
else if( bindingkeyname == "ctrl" ) { binding |= keymodifier::control; }
else if( bindingkeyname == "none" ) { binding = 0; }
else {
// regular key, convert it to glfw key code
auto const keylookup = nametokeymap.find( bindingkeyname );
if( keylookup == nametokeymap.end() ) {
WriteLog( "Keyboard binding included unrecognized key, \"" + bindingkeyname + "\"" );
// Parse command description, starting with "//".
// TODO: At some point, rewind this and add translation keys instead for multilingual support.
// This can't be done now as by default this would destroy all command descriptions,
// which are used by Starter.
// Do this when szczawik's Starter becomes deprecated or implements command descriptions in some other way.
WriteLog("got: \"" + bindingkeyname + "\"");
if (descriptionStarted) {
if (description.size() > 0) {
description += " ";
}
description += bindingkeyname;
} else if (bindingkeyname == "//") {
descriptionStarted = true;
} else {
if( bindingkeyname == "shift" ) { keycode |= keymodifier::shift; }
else if( bindingkeyname == "ctrl" ) { keycode |= keymodifier::control; }
else if( bindingkeyname == "none" ) { keycode = 0; }
else {
// replace any existing binding, preserve modifiers
// (protection from cases where there's more than one key listed in the entry)
binding = keylookup->second | ( binding & 0xffff0000 );
// regular key, convert it to glfw key code
auto const keylookup = nametokeymap.find( bindingkeyname );
if( keylookup == nametokeymap.end() ) {
WriteLog( "Keyboard binding included unrecognized key, \"" + bindingkeyname + "\"" );
}
else {
// replace any existing binding, preserve modifiers
// (protection from cases where there's more than one key listed in the entry)
keycode = keylookup->second | ( keycode & 0xffff0000 );
}
}
}
if( ( binding & 0xffff ) != 0 ) {
m_bindingsetups.insert_or_assign(lookup->second, binding);
}
std::tuple<int, std::string> binding{keycode, description};
m_bindingsetups.insert_or_assign(lookup->second, binding);
}
}
}
@@ -202,20 +220,25 @@ void keyboard_input::dump_bindings()
return;
}
for (const std::pair<user_command, int> &binding : m_bindingsetups) {
for (const std::pair<user_command, std::tuple<int, std::string>> &binding : m_bindingsetups) {
stream << simulation::Commands_descriptions[static_cast<std::size_t>(binding.first)].name << ' ';
auto it = keytonamemap.find(binding.second & 0xFFFF);
int keycode = std::get<int>(binding.second);
auto it = keytonamemap.find(keycode & 0xFFFF);
if (it != keytonamemap.end()) {
if (binding.second & keymodifier::control)
if (keycode & keymodifier::control)
stream << "ctrl ";
if (binding.second & keymodifier::shift)
if (keycode & keymodifier::shift)
stream << "shift ";
stream << it->second << "\r\n";
stream << it->second;
} else {
stream << "none\r\n";
stream << "none";
}
std::string description = std::get<std::string>(binding.second);
if (description.size() > 0)
stream << " // " << description << "\r\n";
}
}
@@ -295,7 +318,7 @@ keyboard_input::bind() {
for( auto const &bindingsetup : m_bindingsetups ) {
m_bindings[ bindingsetup.second ] = bindingsetup.first;
m_bindings[ std::get<int>(bindingsetup.second) ] = bindingsetup.first;
}
// cache movement key bindings