1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Introduce KeyPress variant for GameKeyType

This commit is contained in:
y5nw 2025-06-01 10:20:19 +02:00
parent 88d887cf8d
commit c58814e703
2 changed files with 74 additions and 38 deletions

View file

@ -13,13 +13,6 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
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 */ \ #define DEFINEKEY1(x, lang) /* Irrlicht key without character */ \
{ #x, irr::x, L'\0', lang }, { #x, irr::x, L'\0', lang },
#define DEFINEKEY2(x, ch, lang) /* Irrlicht key with character */ \ #define DEFINEKEY2(x, ch, lang) /* Irrlicht key with character */ \
@ -33,7 +26,7 @@ struct table_key {
#define N_(text) text #define N_(text) text
static std::vector<table_key> table = { std::vector<KeyPress::table_key> KeyPress::keycode_table = {
// Keys that can be reliably mapped between Char and Key // Keys that can be reliably mapped between Char and Key
DEFINEKEY3(0) DEFINEKEY3(0)
DEFINEKEY3(1) DEFINEKEY3(1)
@ -223,18 +216,17 @@ static std::vector<table_key> table = {
DEFINEKEY5("^") DEFINEKEY5("^")
DEFINEKEY5("_") DEFINEKEY5("_")
}; };
const KeyPress::table_key KeyPress::invalid_key = {"", irr::KEY_UNKNOWN, L'\0', ""};
static const table_key invalid_key = {"", irr::KEY_UNKNOWN, L'\0', ""};
#undef N_ #undef N_
static const table_key &lookup_keychar(wchar_t Char) const KeyPress::table_key &KeyPress::lookupKeychar(wchar_t Char)
{ {
if (Char == L'\0') if (Char == L'\0')
return invalid_key; return invalid_key;
for (const auto &table_key : table) { for (const auto &table_key : keycode_table) {
if (table_key.Char == Char) if (table_key.Char == Char)
return table_key; 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. // Create a new entry in the lookup table if one is not available.
auto newsym = wide_to_utf8(std::wstring_view(&Char, 1)); auto newsym = wide_to_utf8(std::wstring_view(&Char, 1));
table_key new_key {newsym, irr::KEY_KEY_CODES_COUNT, Char, newsym}; 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)) if (!Keycode::isValid(key))
return invalid_key; return invalid_key;
for (const auto &table_key : table) { for (const auto &table_key : keycode_table) {
if (table_key.Key == key) if (table_key.Key == key)
return table_key; return table_key;
} }
@ -258,12 +250,12 @@ static const table_key &lookup_keykey(irr::EKEY_CODE key)
return invalid_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()) if (name.empty())
return invalid_key; return invalid_key;
for (const auto &table_key : table) { for (const auto &table_key : keycode_table) {
if (table_key.Name == name) if (table_key.Name == name)
return table_key; return table_key;
} }
@ -271,34 +263,43 @@ static const table_key &lookup_keyname(std::string_view name)
auto wname = utf8_to_wide(name); auto wname = utf8_to_wide(name);
if (wname.empty()) if (wname.empty())
return invalid_key; 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); auto key = RenderingEngine::get_raw_device()->getKeyFromScancode(scancode);
return std::holds_alternative<EKEY_CODE>(key) ? return std::holds_alternative<EKEY_CODE>(key) ?
lookup_keykey(std::get<irr::EKEY_CODE>(key)) : lookupKeykey(std::get<irr::EKEY_CODE>(key)) :
lookup_keychar(std::get<wchar_t>(key)); lookupKeychar(std::get<wchar_t>(key));
} }
static const table_key &lookup_scancode(const std::variant<u32, irr::EKEY_CODE> &scancode) const KeyPress::table_key &KeyPress::lookupScancode() const
{ {
return std::holds_alternative<irr::EKEY_CODE>(scancode) ? switch (getType()) {
lookup_keykey(std::get<irr::EKEY_CODE>(scancode)) : case KeyPress::KEYCODE_INPUT:
lookup_scancode(std::get<u32>(scancode)); return lookupKeykey(std::get<irr::EKEY_CODE>(scancode));
case KeyPress::SCANCODE_INPUT:
return lookupScancode(std::get<u32>(scancode));
default:
return invalid_key;
}
} }
void KeyPress::loadFromKey(irr::EKEY_CODE keycode, wchar_t keychar) 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::EKEY_CODE>(irr_scancode))
scancode.emplace<irr::EKEY_CODE>(std::get<irr::EKEY_CODE>(irr_scancode));
else
scancode.emplace<u32>(std::get<u32>(irr_scancode));
} }
KeyPress::KeyPress(const std::string &name) KeyPress::KeyPress(const std::string &name)
{ {
if (loadFromScancode(name)) if (loadFromScancode(name))
return; return;
const auto &key = lookup_keyname(name); const auto &key = lookupKeyname(name);
loadFromKey(key.Key, key.Char); loadFromKey(key.Key, key.Char);
} }
@ -325,7 +326,7 @@ std::string KeyPress::formatScancode() const
std::string KeyPress::sym() const std::string KeyPress::sym() const
{ {
std::string name = lookup_scancode(scancode).Name; std::string name = lookupScancode().Name;
if (USE_SDL2 || name.empty()) if (USE_SDL2 || name.empty())
if (auto newname = formatScancode(); !newname.empty()) if (auto newname = formatScancode(); !newname.empty())
return newname; return newname;
@ -334,7 +335,7 @@ std::string KeyPress::sym() const
std::string KeyPress::name() const std::string KeyPress::name() const
{ {
const auto &name = lookup_scancode(scancode).LangName; const auto &name = lookupScancode().LangName;
if (!name.empty()) if (!name.empty())
return name; return name;
return formatScancode(); return formatScancode();
@ -342,12 +343,12 @@ std::string KeyPress::name() const
irr::EKEY_CODE KeyPress::getKeycode() const irr::EKEY_CODE KeyPress::getKeycode() const
{ {
return lookup_scancode(scancode).Key; return lookupScancode().Key;
} }
wchar_t KeyPress::getKeychar() const wchar_t KeyPress::getKeychar() const
{ {
return lookup_scancode(scancode).Char; return lookupScancode().Char;
} }
bool KeyPress::loadFromScancode(const std::string &name) bool KeyPress::loadFromScancode(const std::string &name)
@ -375,6 +376,20 @@ KeyPress KeyPress::getSpecialKey(const std::string &name)
return key; return key;
} }
KeyPress::operator bool() const
{
switch (getType()) {
case KeyPress::SCANCODE_INPUT:
return std::get<u32>(scancode) != 0;
case KeyPress::KEYCODE_INPUT:
return Keycode::isValid(std::get<irr::EKEY_CODE>(scancode));
case KeyPress::GAME_ACTION_INPUT:
return std::get<GameKeyType>(scancode) < KeyType::INTERNAL_ENUM_COUNT;
default:
return false;
}
}
/* /*
Key config Key config
*/ */

View file

@ -5,6 +5,7 @@
#pragma once #pragma once
#include "irrlichttypes.h" #include "irrlichttypes.h"
#include "keys.h"
#include <Keycodes.h> #include <Keycodes.h>
#include <IEventReceiver.h> #include <IEventReceiver.h>
#include <string> #include <string>
@ -17,6 +18,12 @@
class KeyPress class KeyPress
{ {
public: 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() = default;
KeyPress(const std::string &name); KeyPress(const std::string &name);
@ -55,18 +62,32 @@ public:
return scancode < o.scancode; return scancode < o.scancode;
} }
// Check whether the keypress is valid InputType getType() const {
operator bool() const return static_cast<InputType>(scancode.index());
{
return std::holds_alternative<irr::EKEY_CODE>(scancode) ?
Keycode::isValid(std::get<irr::EKEY_CODE>(scancode)) :
std::get<u32>(scancode) != 0;
} }
// Check whether the keypress is valid
operator bool() const;
static KeyPress getSpecialKey(const std::string &name); static KeyPress getSpecialKey(const std::string &name);
private: private:
using value_type = std::variant<u32, irr::EKEY_CODE>; 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<table_key> 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<u32, irr::EKEY_CODE, GameKeyType>;
bool loadFromScancode(const std::string &name); bool loadFromScancode(const std::string &name);
void loadFromKey(irr::EKEY_CODE keycode, wchar_t keychar); void loadFromKey(irr::EKEY_CODE keycode, wchar_t keychar);
std::string formatScancode() const; std::string formatScancode() const;