diff --git a/src/client/keycode.cpp b/src/client/keycode.cpp index 86404708c..3f6d74118 100644 --- a/src/client/keycode.cpp +++ b/src/client/keycode.cpp @@ -13,13 +13,6 @@ #include #include -struct table_key { - std::string Name; // An EKEY_CODE 'symbol' name as a string - irr::EKEY_CODE Key; - wchar_t Char; // L'\0' means no character assigned - std::string LangName; // empty string means it doesn't have a human description -}; - #define DEFINEKEY1(x, lang) /* Irrlicht key without character */ \ { #x, irr::x, L'\0', lang }, #define DEFINEKEY2(x, ch, lang) /* Irrlicht key with character */ \ @@ -33,7 +26,7 @@ struct table_key { #define N_(text) text -static std::vector table = { +std::vector KeyPress::keycode_table = { // Keys that can be reliably mapped between Char and Key DEFINEKEY3(0) DEFINEKEY3(1) @@ -223,18 +216,17 @@ static std::vector table = { DEFINEKEY5("^") DEFINEKEY5("_") }; - -static const table_key invalid_key = {"", irr::KEY_UNKNOWN, L'\0', ""}; +const KeyPress::table_key KeyPress::invalid_key = {"", irr::KEY_UNKNOWN, L'\0', ""}; #undef N_ -static const table_key &lookup_keychar(wchar_t Char) +const KeyPress::table_key &KeyPress::lookupKeychar(wchar_t Char) { if (Char == L'\0') return invalid_key; - for (const auto &table_key : table) { + for (const auto &table_key : keycode_table) { if (table_key.Char == Char) return table_key; } @@ -242,15 +234,15 @@ static const table_key &lookup_keychar(wchar_t Char) // Create a new entry in the lookup table if one is not available. auto newsym = wide_to_utf8(std::wstring_view(&Char, 1)); table_key new_key {newsym, irr::KEY_KEY_CODES_COUNT, Char, newsym}; - return table.emplace_back(std::move(new_key)); + return keycode_table.emplace_back(std::move(new_key)); } -static const table_key &lookup_keykey(irr::EKEY_CODE key) +const KeyPress::table_key &KeyPress::lookupKeykey(irr::EKEY_CODE key) { if (!Keycode::isValid(key)) return invalid_key; - for (const auto &table_key : table) { + for (const auto &table_key : keycode_table) { if (table_key.Key == key) return table_key; } @@ -258,12 +250,12 @@ static const table_key &lookup_keykey(irr::EKEY_CODE key) return invalid_key; } -static const table_key &lookup_keyname(std::string_view name) +const KeyPress::table_key &KeyPress::lookupKeyname(std::string_view name) { if (name.empty()) return invalid_key; - for (const auto &table_key : table) { + for (const auto &table_key : keycode_table) { if (table_key.Name == name) return table_key; } @@ -271,34 +263,43 @@ static const table_key &lookup_keyname(std::string_view name) auto wname = utf8_to_wide(name); if (wname.empty()) return invalid_key; - return lookup_keychar(wname[0]); + return lookupKeychar(wname[0]); } -static const table_key &lookup_scancode(const u32 scancode) +const KeyPress::table_key &KeyPress::lookupScancode(const u32 scancode) { auto key = RenderingEngine::get_raw_device()->getKeyFromScancode(scancode); return std::holds_alternative(key) ? - lookup_keykey(std::get(key)) : - lookup_keychar(std::get(key)); + lookupKeykey(std::get(key)) : + lookupKeychar(std::get(key)); } -static const table_key &lookup_scancode(const std::variant &scancode) +const KeyPress::table_key &KeyPress::lookupScancode() const { - return std::holds_alternative(scancode) ? - lookup_keykey(std::get(scancode)) : - lookup_scancode(std::get(scancode)); + switch (getType()) { + case KeyPress::KEYCODE_INPUT: + return lookupKeykey(std::get(scancode)); + case KeyPress::SCANCODE_INPUT: + return lookupScancode(std::get(scancode)); + default: + return invalid_key; + } } void KeyPress::loadFromKey(irr::EKEY_CODE keycode, wchar_t keychar) { - scancode = RenderingEngine::get_raw_device()->getScancodeFromKey(Keycode(keycode, keychar)); + auto irr_scancode = RenderingEngine::get_raw_device()->getScancodeFromKey(Keycode(keycode, keychar)); + if (std::holds_alternative(irr_scancode)) + scancode.emplace(std::get(irr_scancode)); + else + scancode.emplace(std::get(irr_scancode)); } KeyPress::KeyPress(const std::string &name) { if (loadFromScancode(name)) return; - const auto &key = lookup_keyname(name); + const auto &key = lookupKeyname(name); loadFromKey(key.Key, key.Char); } @@ -325,7 +326,7 @@ std::string KeyPress::formatScancode() const std::string KeyPress::sym() const { - std::string name = lookup_scancode(scancode).Name; + std::string name = lookupScancode().Name; if (USE_SDL2 || name.empty()) if (auto newname = formatScancode(); !newname.empty()) return newname; @@ -334,7 +335,7 @@ std::string KeyPress::sym() const std::string KeyPress::name() const { - const auto &name = lookup_scancode(scancode).LangName; + const auto &name = lookupScancode().LangName; if (!name.empty()) return name; return formatScancode(); @@ -342,12 +343,12 @@ std::string KeyPress::name() const irr::EKEY_CODE KeyPress::getKeycode() const { - return lookup_scancode(scancode).Key; + return lookupScancode().Key; } wchar_t KeyPress::getKeychar() const { - return lookup_scancode(scancode).Char; + return lookupScancode().Char; } bool KeyPress::loadFromScancode(const std::string &name) @@ -375,6 +376,20 @@ KeyPress KeyPress::getSpecialKey(const std::string &name) return key; } +KeyPress::operator bool() const +{ + switch (getType()) { + case KeyPress::SCANCODE_INPUT: + return std::get(scancode) != 0; + case KeyPress::KEYCODE_INPUT: + return Keycode::isValid(std::get(scancode)); + case KeyPress::GAME_ACTION_INPUT: + return std::get(scancode) < KeyType::INTERNAL_ENUM_COUNT; + default: + return false; + } +} + /* Key config */ diff --git a/src/client/keycode.h b/src/client/keycode.h index 0fd4f24b9..63b0f5630 100644 --- a/src/client/keycode.h +++ b/src/client/keycode.h @@ -5,6 +5,7 @@ #pragma once #include "irrlichttypes.h" +#include "keys.h" #include #include #include @@ -17,6 +18,12 @@ class KeyPress { public: + enum InputType { + SCANCODE_INPUT, // Keyboard input (scancodes) + KEYCODE_INPUT, // (Deprecated) irr::EKEY_CODE-based keyboard and mouse input + GAME_ACTION_INPUT, // GameKeyType input passed by touchscreen buttons + }; + KeyPress() = default; KeyPress(const std::string &name); @@ -55,18 +62,32 @@ public: return scancode < o.scancode; } - // Check whether the keypress is valid - operator bool() const - { - return std::holds_alternative(scancode) ? - Keycode::isValid(std::get(scancode)) : - std::get(scancode) != 0; + InputType getType() const { + return static_cast(scancode.index()); } + // Check whether the keypress is valid + operator bool() const; + static KeyPress getSpecialKey(const std::string &name); private: - using value_type = std::variant; + struct table_key { // internal keycode lookup table + std::string Name; // An EKEY_CODE 'symbol' name as a string + irr::EKEY_CODE Key; + wchar_t Char; // L'\0' means no character assigned + std::string LangName; // empty string means it doesn't have a human description + }; + static const table_key invalid_key; + static std::vector keycode_table; + static const table_key &lookupKeychar(wchar_t Char); + static const table_key &lookupKeykey(irr::EKEY_CODE key); + static const table_key &lookupKeyname(std::string_view name); + static const table_key &lookupScancode(const u32 scancode); + const table_key &lookupScancode() const; + + using value_type = std::variant; + bool loadFromScancode(const std::string &name); void loadFromKey(irr::EKEY_CODE keycode, wchar_t keychar); std::string formatScancode() const;