partial
This commit is contained in:
parent
246c35316c
commit
cd8dee2779
@ -342,6 +342,26 @@ public:
|
||||
{
|
||||
return video::isDriverSupported(driver);
|
||||
}
|
||||
|
||||
// This is a trivial (near-identity) mapping for converting between scancodes and keycodes for devices that do
|
||||
// not implement this.
|
||||
|
||||
//! Get the scancode of the corresponding keycode.
|
||||
virtual u32 getScancodeFromKey(const KeyCode &key) const
|
||||
{
|
||||
return key.index() == 0 ? std::get<EKEY_CODE>(key) : KEY_KEY_CODES_COUNT + std::get<wchar_t>(key);
|
||||
}
|
||||
|
||||
//! Get the keycode of the corresponding scancode.
|
||||
virtual KeyCode getKeyFromScancode(const u32 scancode) const
|
||||
{
|
||||
KeyCode key;
|
||||
if (scancode < KEY_KEY_CODES_COUNT)
|
||||
key.emplace<EKEY_CODE>((EKEY_CODE)scancode);
|
||||
else
|
||||
key.emplace<wchar_t>(scancode - KEY_KEY_CODES_COUNT);
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
@ -3,6 +3,7 @@
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#pragma once
|
||||
#include <variant>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -182,4 +183,29 @@ enum EKEY_CODE
|
||||
KEY_KEY_CODES_COUNT = 0x100 // this is not a key, but the amount of keycodes there are.
|
||||
};
|
||||
|
||||
class KeyCode : public std::variant<EKEY_CODE, wchar_t> {
|
||||
using super = std::variant<EKEY_CODE, wchar_t>;
|
||||
public:
|
||||
KeyCode() : KeyCode(KEY_KEY_CODES_COUNT, L'\0') {}
|
||||
|
||||
KeyCode(EKEY_CODE code, wchar_t ch)
|
||||
{
|
||||
emplace(code, ch);
|
||||
}
|
||||
|
||||
using super::emplace;
|
||||
void emplace(EKEY_CODE code, wchar_t ch)
|
||||
{
|
||||
if (isValid(code))
|
||||
emplace<EKEY_CODE>(code);
|
||||
else
|
||||
emplace<wchar_t>(ch);
|
||||
}
|
||||
|
||||
static bool isValid(EKEY_CODE code)
|
||||
{
|
||||
return code > 0 && code < KEY_KEY_CODES_COUNT;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
@ -220,6 +220,31 @@ int CIrrDeviceSDL::findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtK
|
||||
}
|
||||
}
|
||||
|
||||
u32 CIrrDeviceSDL::getScancodeFromKey(const KeyCode &key) const
|
||||
{
|
||||
u32 keynum = 0;
|
||||
if (key.index() == 0) {
|
||||
auto keycode = std::get<EKEY_CODE>(key);
|
||||
for (const auto &entry: KeyMap) {
|
||||
if (entry.second == keycode) {
|
||||
keynum = entry.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
keynum = std::get<wchar_t>(key);
|
||||
}
|
||||
return SDL_GetScancodeFromKey(keynum);
|
||||
}
|
||||
|
||||
KeyCode CIrrDeviceSDL::getKeyFromScancode(const u32 scancode) const
|
||||
{
|
||||
auto keycode = SDL_GetKeyFromScancode((SDL_Scancode)scancode);
|
||||
const auto &keyentry = KeyMap.find(keycode);
|
||||
auto irrcode = keyentry != KeyMap.end() ? keyentry->second : KEY_UNKNOWN;
|
||||
return KeyCode(irrcode, keycode);
|
||||
}
|
||||
|
||||
void CIrrDeviceSDL::resetReceiveTextInputEvents()
|
||||
{
|
||||
gui::IGUIElement *elem = GUIEnvironment->getFocus();
|
||||
@ -815,6 +840,21 @@ bool CIrrDeviceSDL::run()
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP: {
|
||||
auto keysym = SDL_event.key.keysym.sym;
|
||||
auto scancode = SDL_event.key.keysym.scancode;
|
||||
|
||||
// Treat AC_BACK as the Escape key
|
||||
if (scancode == SDL_SCANCODE_AC_BACK || scancode == SDL_SCANCODE_ESCAPE)
|
||||
{
|
||||
if (SDL_event.type == SDL_KEYDOWN)
|
||||
escapeKeys.insert(scancode);
|
||||
else
|
||||
escapeKeys.erase(scancode);
|
||||
if (SDL_event.type == SDL_KEYUP && !escapeKeys.empty())
|
||||
break; // avoid sending KEYUP twice if AC_BACK and ESCAPE are both released
|
||||
scancode = SDL_SCANCODE_ESCAPE;
|
||||
keysym = SDLK_ESCAPE;
|
||||
}
|
||||
|
||||
const auto &entry = KeyMap.find(keysym);
|
||||
auto key = entry == KeyMap.end() ? KEY_UNKNOWN : entry->second;
|
||||
|
||||
@ -832,6 +872,8 @@ bool CIrrDeviceSDL::run()
|
||||
irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL) != 0;
|
||||
irrevent.KeyInput.Char = findCharToPassToIrrlicht(keysym, key,
|
||||
(SDL_event.key.keysym.mod & KMOD_NUM) != 0);
|
||||
irrevent.KeyInput.SystemKeyCode = scancode;
|
||||
|
||||
postEventFromUser(irrevent);
|
||||
} break;
|
||||
|
||||
@ -1298,9 +1340,6 @@ void CIrrDeviceSDL::createKeyMap()
|
||||
|
||||
// buttons missing
|
||||
|
||||
// Android back button = ESC
|
||||
KeyMap.emplace(SDLK_AC_BACK, KEY_ESCAPE);
|
||||
|
||||
KeyMap.emplace(SDLK_BACKSPACE, KEY_BACK);
|
||||
KeyMap.emplace(SDLK_TAB, KEY_TAB);
|
||||
KeyMap.emplace(SDLK_CLEAR, KEY_CLEAR);
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -286,6 +288,9 @@ private:
|
||||
// Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
|
||||
static int findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock);
|
||||
|
||||
virtual u32 getScancodeFromKey(const KeyCode &key) const override;
|
||||
virtual KeyCode getKeyFromScancode(const u32 scancode) const override;
|
||||
|
||||
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
|
||||
void resetReceiveTextInputEvents();
|
||||
|
||||
@ -324,6 +329,8 @@ private:
|
||||
|
||||
s32 CurrentTouchCount;
|
||||
bool IsInBackground;
|
||||
|
||||
std::unordered_set<SDL_Scancode> escapeKeys;
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
@ -143,7 +143,7 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
|
||||
// Remember whether each key is down or up
|
||||
if (event.EventType == irr::EET_KEY_INPUT_EVENT) {
|
||||
const KeyPress keyCode(event.KeyInput);
|
||||
if (keysListenedFor[keyCode]) {
|
||||
if (keyCode && keysListenedFor[keyCode]) {
|
||||
if (event.KeyInput.PressedDown) {
|
||||
if (!IsKeyDown(keyCode))
|
||||
keyWasPressed.set(keyCode);
|
||||
|
@ -6,15 +6,17 @@
|
||||
#include "settings.h"
|
||||
#include "log.h"
|
||||
#include "debug.h"
|
||||
#include "renderingengine.h"
|
||||
#include "util/hex.h"
|
||||
#include "util/string.h"
|
||||
#include "util/basic_macros.h"
|
||||
#include <vector>
|
||||
|
||||
struct table_key {
|
||||
const char *Name;
|
||||
std::string Name;
|
||||
irr::EKEY_CODE Key;
|
||||
wchar_t Char; // L'\0' means no character assigned
|
||||
const char *LangName; // NULL means it doesn't have a human description
|
||||
std::string LangName; // NULL means it doesn't have a human description
|
||||
};
|
||||
|
||||
#define DEFINEKEY1(x, lang) /* Irrlicht key without character */ \
|
||||
@ -30,7 +32,7 @@ struct table_key {
|
||||
|
||||
#define N_(text) text
|
||||
|
||||
static const struct table_key table[] = {
|
||||
static std::vector<table_key> table = {
|
||||
// Keys that can be reliably mapped between Char and Key
|
||||
DEFINEKEY3(0)
|
||||
DEFINEKEY3(1)
|
||||
@ -126,7 +128,7 @@ static const struct table_key table[] = {
|
||||
DEFINEKEY1(KEY_ADD, N_("Numpad +"))
|
||||
DEFINEKEY1(KEY_SEPARATOR, N_("Numpad ."))
|
||||
DEFINEKEY1(KEY_SUBTRACT, N_("Numpad -"))
|
||||
DEFINEKEY1(KEY_DECIMAL, NULL)
|
||||
DEFINEKEY1(KEY_DECIMAL, N_("Numpad ."))
|
||||
DEFINEKEY1(KEY_DIVIDE, N_("Numpad /"))
|
||||
DEFINEKEY4(1)
|
||||
DEFINEKEY4(2)
|
||||
@ -221,33 +223,16 @@ static const struct table_key table[] = {
|
||||
DEFINEKEY5("_")
|
||||
};
|
||||
|
||||
static const table_key invalid_key = {"", irr::KEY_UNKNOWN, L'\0', ""};
|
||||
|
||||
#undef N_
|
||||
|
||||
|
||||
static const table_key &lookup_keyname(const char *name)
|
||||
{
|
||||
for (const auto &table_key : table) {
|
||||
if (strcmp(table_key.Name, name) == 0)
|
||||
return table_key;
|
||||
}
|
||||
|
||||
throw UnknownKeycode(name);
|
||||
}
|
||||
|
||||
static const table_key &lookup_keykey(irr::EKEY_CODE key)
|
||||
{
|
||||
for (const auto &table_key : table) {
|
||||
if (table_key.Key == key)
|
||||
return table_key;
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
os << "<Keycode " << (int) key << ">";
|
||||
throw UnknownKeycode(os.str().c_str());
|
||||
}
|
||||
|
||||
static const table_key &lookup_keychar(wchar_t Char)
|
||||
{
|
||||
if (Char == L'\0')
|
||||
return invalid_key;
|
||||
|
||||
for (const auto &table_key : table) {
|
||||
if (table_key.Char == Char)
|
||||
return table_key;
|
||||
@ -255,88 +240,73 @@ static const table_key &lookup_keychar(wchar_t Char)
|
||||
|
||||
std::ostringstream os;
|
||||
os << "<Char " << hex_encode((char*) &Char, sizeof(wchar_t)) << ">";
|
||||
throw UnknownKeycode(os.str().c_str());
|
||||
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));
|
||||
}
|
||||
|
||||
KeyPress::KeyPress(const char *name)
|
||||
static const table_key &lookup_keyname(const std::string_view &name)
|
||||
{
|
||||
if (strlen(name) == 0) {
|
||||
Key = irr::KEY_KEY_CODES_COUNT;
|
||||
Char = L'\0';
|
||||
m_name = "";
|
||||
return;
|
||||
if (name.empty())
|
||||
return invalid_key;
|
||||
|
||||
for (const auto &table_key : table) {
|
||||
if (table_key.Name == name)
|
||||
return table_key;
|
||||
}
|
||||
|
||||
if (strlen(name) <= 4) {
|
||||
// Lookup by resulting character
|
||||
int chars_read = mbtowc(&Char, name, 1);
|
||||
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
|
||||
try {
|
||||
auto &k = lookup_keychar(Char);
|
||||
m_name = k.Name;
|
||||
Key = k.Key;
|
||||
return;
|
||||
} catch (UnknownKeycode &e) {};
|
||||
} else {
|
||||
// Lookup by name
|
||||
m_name = name;
|
||||
try {
|
||||
auto &k = lookup_keyname(name);
|
||||
Key = k.Key;
|
||||
Char = k.Char;
|
||||
return;
|
||||
} catch (UnknownKeycode &e) {};
|
||||
auto wname = utf8_to_wide(name);
|
||||
if (wname.empty())
|
||||
return invalid_key;
|
||||
return lookup_keychar(wname[0]);
|
||||
}
|
||||
|
||||
static const table_key &lookup_keykey(irr::EKEY_CODE key)
|
||||
{
|
||||
if (!KeyCode::isValid(key))
|
||||
return invalid_key;
|
||||
|
||||
for (const auto &table_key : table) {
|
||||
if (table_key.Key == key)
|
||||
return table_key;
|
||||
}
|
||||
|
||||
// It's not a known key, complain and try to do something
|
||||
Key = irr::KEY_KEY_CODES_COUNT;
|
||||
int chars_read = mbtowc(&Char, name, 1);
|
||||
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
|
||||
m_name = "";
|
||||
warningstream << "KeyPress: Unknown key '" << name
|
||||
<< "', falling back to first char." << std::endl;
|
||||
std::ostringstream os;
|
||||
os << "<Keycode " << (int) key << ">";
|
||||
return invalid_key;
|
||||
}
|
||||
|
||||
KeyPress::KeyPress(const irr::SEvent::SKeyInput &in, bool prefer_character)
|
||||
static const table_key &lookup_scancode(const u32 scancode)
|
||||
{
|
||||
if (prefer_character)
|
||||
Key = irr::KEY_KEY_CODES_COUNT;
|
||||
else
|
||||
Key = in.Key;
|
||||
Char = in.Char;
|
||||
|
||||
try {
|
||||
if (valid_kcode(Key))
|
||||
m_name = lookup_keykey(Key).Name;
|
||||
else
|
||||
m_name = lookup_keychar(Char).Name;
|
||||
} catch (UnknownKeycode &e) {
|
||||
m_name.clear();
|
||||
};
|
||||
auto key = RenderingEngine::get_raw_device()->getKeyFromScancode(scancode);
|
||||
return key.index() == 0 ? lookup_keykey(std::get<irr::EKEY_CODE>(key)) : lookup_keychar(std::get<wchar_t>(key));
|
||||
}
|
||||
|
||||
const char *KeyPress::sym() const
|
||||
KeyPress::KeyPress(const std::string_view &name)
|
||||
{
|
||||
return m_name.c_str();
|
||||
const auto &key = lookup_keyname(name);
|
||||
KeyCode keycode(key.Key, key.Char);
|
||||
scancode = RenderingEngine::get_raw_device()->getScancodeFromKey(keycode);
|
||||
}
|
||||
|
||||
const char *KeyPress::name() const
|
||||
std::string KeyPress::sym() const
|
||||
{
|
||||
if (m_name.empty())
|
||||
return "";
|
||||
const char *ret;
|
||||
if (valid_kcode(Key))
|
||||
ret = lookup_keykey(Key).LangName;
|
||||
else
|
||||
ret = lookup_keychar(Char).LangName;
|
||||
return ret ? ret : "<Unnamed key>";
|
||||
return lookup_scancode(scancode).Name;
|
||||
}
|
||||
|
||||
const KeyPress EscapeKey("KEY_ESCAPE");
|
||||
std::string KeyPress::name() const
|
||||
{
|
||||
return lookup_scancode(scancode).LangName;
|
||||
}
|
||||
|
||||
const KeyPress LMBKey("KEY_LBUTTON");
|
||||
const KeyPress MMBKey("KEY_MBUTTON");
|
||||
const KeyPress RMBKey("KEY_RBUTTON");
|
||||
std::unordered_map<std::string, KeyPress> KeyPress::specialKeyCache;
|
||||
const KeyPress &KeyPress::getSpecialKey(const std::string &name)
|
||||
{
|
||||
auto &key = specialKeyCache[name];
|
||||
if (!key)
|
||||
key = KeyPress(name);
|
||||
return key;
|
||||
}
|
||||
|
||||
/*
|
||||
Key config
|
||||
@ -352,7 +322,7 @@ const KeyPress &getKeySetting(const char *settingname)
|
||||
return n->second;
|
||||
|
||||
auto &ref = g_key_setting_cache[settingname];
|
||||
ref = g_settings->get(settingname).c_str();
|
||||
ref = std::string_view(g_settings->get(settingname));
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
@ -4,57 +4,49 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "exceptions.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include <Keycodes.h>
|
||||
#include <IEventReceiver.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class UnknownKeycode : public BaseException
|
||||
{
|
||||
public:
|
||||
UnknownKeycode(const char *s) :
|
||||
BaseException(s) {};
|
||||
};
|
||||
|
||||
/* A key press, consisting of either an Irrlicht keycode
|
||||
or an actual char */
|
||||
|
||||
/* A key press, consisting of a scancode or a keycode */
|
||||
class KeyPress
|
||||
{
|
||||
public:
|
||||
KeyPress() = default;
|
||||
KeyPress() {};
|
||||
|
||||
KeyPress(const char *name);
|
||||
KeyPress(const std::string_view &name);
|
||||
|
||||
KeyPress(const irr::SEvent::SKeyInput &in, bool prefer_character = false);
|
||||
KeyPress(const irr::SEvent::SKeyInput &in) :
|
||||
scancode(in.SystemKeyCode) {};
|
||||
|
||||
bool operator==(const KeyPress &o) const
|
||||
{
|
||||
return (Char > 0 && Char == o.Char) || (valid_kcode(Key) && Key == o.Key);
|
||||
std::string sym() const;
|
||||
std::string name() const;
|
||||
|
||||
bool operator==(const KeyPress &o) const {
|
||||
return scancode == o.scancode;
|
||||
}
|
||||
|
||||
const char *sym() const;
|
||||
const char *name() const;
|
||||
|
||||
protected:
|
||||
static bool valid_kcode(irr::EKEY_CODE k)
|
||||
{
|
||||
return k > 0 && k < irr::KEY_KEY_CODES_COUNT;
|
||||
operator bool() const {
|
||||
return scancode != 0;
|
||||
}
|
||||
|
||||
irr::EKEY_CODE Key = irr::KEY_KEY_CODES_COUNT;
|
||||
wchar_t Char = L'\0';
|
||||
std::string m_name = "";
|
||||
static const KeyPress &getSpecialKey(const std::string &name);
|
||||
|
||||
private:
|
||||
u32 scancode = 0;
|
||||
|
||||
static std::unordered_map<std::string, KeyPress> specialKeyCache;
|
||||
};
|
||||
|
||||
// Global defines for convenience
|
||||
|
||||
extern const KeyPress EscapeKey;
|
||||
|
||||
extern const KeyPress LMBKey;
|
||||
extern const KeyPress MMBKey; // Middle Mouse Button
|
||||
extern const KeyPress RMBKey;
|
||||
// This implementation defers creation of the objects to make sure that the
|
||||
// IrrlichtDevice is initialized.
|
||||
#define EscapeKey KeyPress::getSpecialKey("KEY_ESCAPE")
|
||||
#define LMBKey KeyPress::getSpecialKey("KEY_LBUTTON")
|
||||
#define MMBKey KeyPress::getSpecialKey("KEY_MBUTTON") // Middle Mouse Button
|
||||
#define RMBKey KeyPress::getSpecialKey("KEY_RBUTTON")
|
||||
|
||||
// Key configuration getter
|
||||
const KeyPress &getKeySetting(const char *settingname);
|
||||
|
@ -253,8 +253,7 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
|
||||
if (event.EventType == EET_KEY_INPUT_EVENT && active_key
|
||||
&& event.KeyInput.PressedDown) {
|
||||
|
||||
bool prefer_character = shift_down;
|
||||
KeyPress kp(event.KeyInput, prefer_character);
|
||||
KeyPress kp(event.KeyInput);
|
||||
|
||||
if (event.KeyInput.Key == irr::KEY_DELETE)
|
||||
kp = KeyPress(""); // To erase key settings
|
||||
@ -270,7 +269,7 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
|
||||
|
||||
// Display Key already in use message
|
||||
bool key_in_use = false;
|
||||
if (strcmp(kp.sym(), "") != 0) {
|
||||
if (kp) {
|
||||
for (key_setting *ks : key_settings) {
|
||||
if (ks != active_key && ks->key == kp) {
|
||||
key_in_use = true;
|
||||
|
@ -190,13 +190,7 @@ static EKEY_CODE id_to_keycode(touch_gui_button_id id)
|
||||
}
|
||||
assert(!key.empty());
|
||||
std::string resolved = g_settings->get("keymap_" + key);
|
||||
try {
|
||||
code = keyname_to_keycode(resolved.c_str());
|
||||
} catch (UnknownKeycode &e) {
|
||||
code = KEY_UNKNOWN;
|
||||
warningstream << "TouchControls: Unknown key '" << resolved
|
||||
<< "' for '" << key << "', hiding button." << std::endl;
|
||||
}
|
||||
code = keyname_to_keycode(resolved.c_str());
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <string>
|
||||
#include "exceptions.h"
|
||||
#include "client/keycode.h"
|
||||
#include "client/renderingengine.h" // scancode<->keycode conversion
|
||||
|
||||
class TestKeycode : public TestBase {
|
||||
public:
|
||||
@ -24,42 +25,56 @@ static TestKeycode g_test_instance;
|
||||
|
||||
void TestKeycode::runTests(IGameDef *gamedef)
|
||||
{
|
||||
// TODO: How do we test this without an IrrlichtDevice?
|
||||
#if 0
|
||||
TEST(testCreateFromString);
|
||||
TEST(testCreateFromSKeyInput);
|
||||
TEST(testCompare);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define UASSERTEQ_STR(one, two) UASSERT(strcmp(one, two) == 0)
|
||||
#define UASSERTEQ_STR(one, two) UASSERT(one == two)
|
||||
#define UASSERT_HAS_NAME(k) UASSERT(!k.name().empty())
|
||||
|
||||
void TestKeycode::testCreateFromString()
|
||||
{
|
||||
KeyPress k;
|
||||
|
||||
k = KeyPress("");
|
||||
UASSERTEQ_STR(k.sym(), "");
|
||||
UASSERTEQ_STR(k.name(), "");
|
||||
|
||||
// Character key, from char
|
||||
k = KeyPress("R");
|
||||
UASSERTEQ_STR(k.sym(), "KEY_KEY_R");
|
||||
UASSERTCMP(int, >, strlen(k.name()), 0); // should have human description
|
||||
UASSERT_HAS_NAME(k);
|
||||
|
||||
// Character key, from identifier
|
||||
k = KeyPress("KEY_KEY_B");
|
||||
UASSERTEQ_STR(k.sym(), "KEY_KEY_B");
|
||||
UASSERTCMP(int, >, strlen(k.name()), 0);
|
||||
UASSERT_HAS_NAME(k);
|
||||
|
||||
// Non-Character key, from identifier
|
||||
k = KeyPress("KEY_UP");
|
||||
UASSERTEQ_STR(k.sym(), "KEY_UP");
|
||||
UASSERTCMP(int, >, strlen(k.name()), 0);
|
||||
UASSERT_HAS_NAME(k);
|
||||
|
||||
k = KeyPress("KEY_F6");
|
||||
UASSERTEQ_STR(k.sym(), "KEY_F6");
|
||||
UASSERTCMP(int, >, strlen(k.name()), 0);
|
||||
UASSERT_HAS_NAME(k);
|
||||
|
||||
// Irrlicht-unknown key, from char
|
||||
k = KeyPress("/");
|
||||
UASSERTEQ_STR(k.sym(), "/");
|
||||
UASSERTCMP(int, >, strlen(k.name()), 0);
|
||||
UASSERT_HAS_NAME(k);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
static u32 toScancode(Args... args)
|
||||
{
|
||||
return RenderingEngine::get_raw_device()->getScancodeFromKey(KeyCode(args...));
|
||||
}
|
||||
|
||||
void TestKeycode::testCreateFromSKeyInput()
|
||||
@ -68,47 +83,46 @@ void TestKeycode::testCreateFromSKeyInput()
|
||||
irr::SEvent::SKeyInput in;
|
||||
|
||||
// Character key
|
||||
in.Key = irr::KEY_KEY_3;
|
||||
in.Char = L'3';
|
||||
in.SystemKeyCode = toScancode(irr::KEY_KEY_3, L'3');
|
||||
k = KeyPress(in);
|
||||
UASSERTEQ_STR(k.sym(), "KEY_KEY_3");
|
||||
UASSERT_HAS_NAME(k);
|
||||
|
||||
// Non-Character key
|
||||
in.Key = irr::KEY_RSHIFT;
|
||||
in.Char = L'\0';
|
||||
in.SystemKeyCode = toScancode(irr::KEY_RSHIFT, L'\0');
|
||||
k = KeyPress(in);
|
||||
UASSERTEQ_STR(k.sym(), "KEY_RSHIFT");
|
||||
UASSERT_HAS_NAME(k);
|
||||
|
||||
// Irrlicht-unknown key
|
||||
in.Key = irr::KEY_KEY_CODES_COUNT;
|
||||
in.Char = L'?';
|
||||
in.SystemKeyCode = toScancode(KEY_KEY_CODES_COUNT, L'?');
|
||||
k = KeyPress(in);
|
||||
UASSERTEQ_STR(k.sym(), "?");
|
||||
|
||||
// prefer_character mode
|
||||
in.Key = irr::KEY_COMMA;
|
||||
in.Char = L'G';
|
||||
k = KeyPress(in, true);
|
||||
UASSERTEQ_STR(k.sym(), "KEY_KEY_G");
|
||||
UASSERT_HAS_NAME(k);
|
||||
}
|
||||
|
||||
void TestKeycode::testCompare()
|
||||
{
|
||||
// "Empty" key
|
||||
UASSERT(KeyPress() == KeyPress(""));
|
||||
|
||||
// Basic comparison
|
||||
UASSERT(KeyPress("5") == KeyPress("KEY_KEY_5"));
|
||||
UASSERT(!(KeyPress("5") == KeyPress("KEY_NUMPAD5")));
|
||||
|
||||
// Matching char suffices
|
||||
// note: This is a real-world example, Irrlicht maps XK_equal to irr::KEY_PLUS on Linux
|
||||
// TODO: Is this still relevant for scancodes?
|
||||
irr::SEvent::SKeyInput in;
|
||||
/*
|
||||
in.Key = irr::KEY_PLUS;
|
||||
in.Char = L'=';
|
||||
UASSERT(KeyPress("=") == KeyPress(in));
|
||||
*/
|
||||
|
||||
// Matching keycode suffices
|
||||
irr::SEvent::SKeyInput in2;
|
||||
in.Key = in2.Key = irr::KEY_OEM_CLEAR;
|
||||
in.Char = L'\0';
|
||||
in2.Char = L';';
|
||||
in.SystemKeyCode = toScancode(irr::KEY_OEM_CLEAR, L'\0');
|
||||
in2.SystemKeyCode = toScancode(irr::KEY_OEM_CLEAR, L';');
|
||||
UASSERT(KeyPress(in) == KeyPress(in2));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user