Use std::variant for scancode to properly handle mouse keys
This commit is contained in:
parent
b61d50c3ab
commit
c9e53001dc
@ -16,6 +16,7 @@
|
||||
#include "IrrCompileConfig.h"
|
||||
#include "position2d.h"
|
||||
#include "SColor.h" // video::ECOLOR_FORMAT
|
||||
#include <variant>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -343,29 +344,19 @@ 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.
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_SDL_DEVICE_) || USE_SDL2
|
||||
//! Get the scancode of the corresponding keycode.
|
||||
virtual u32 getScancodeFromKey(const Keycode &key) const
|
||||
{
|
||||
if (const auto *keycode = std::get_if<EKEY_CODE>(&key))
|
||||
// treat KEY_UNKNOWN and KEY_KEY_CODES_COUNT as the same and return 0.
|
||||
return Keycode::isValid(*keycode) ? *keycode : 0;
|
||||
const auto keychar = std::get<wchar_t>(key);
|
||||
return keychar == 0 ? 0 : KEY_KEY_CODES_COUNT + keychar;
|
||||
virtual std::variant<u32, EKEY_CODE> getScancodeFromKey(const Keycode &key) const {
|
||||
if (auto pv = std::get_if<EKEY_CODE>(&key))
|
||||
return *pv;
|
||||
return (u32)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;
|
||||
virtual Keycode getKeyFromScancode(const u32 scancode) const {
|
||||
return Keycode(KEY_UNKNOWN, (wchar_t)scancode);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "COSOperator.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <unordered_set>
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include <SDL_video.h>
|
||||
|
||||
@ -27,6 +28,14 @@
|
||||
|
||||
#include "CSDLManager.h"
|
||||
|
||||
// Since SDL doesn't have mouse keys as keycodes we fall back to EKEY_CODE
|
||||
static const std::unordered_set<irr::EKEY_CODE> fake_keys = {
|
||||
irr::KEY_LBUTTON, irr::KEY_MBUTTON, irr::KEY_RBUTTON, irr::KEY_XBUTTON1, irr::KEY_XBUTTON2
|
||||
};
|
||||
static inline bool is_fake_key(irr::EKEY_CODE key) {
|
||||
return fake_keys.find(key) != fake_keys.end();
|
||||
}
|
||||
|
||||
static int SDLDeviceInstances = 0;
|
||||
|
||||
namespace irr
|
||||
@ -220,10 +229,12 @@ int CIrrDeviceSDL::findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtK
|
||||
}
|
||||
}
|
||||
|
||||
u32 CIrrDeviceSDL::getScancodeFromKey(const Keycode &key) const
|
||||
std::variant<u32, EKEY_CODE> CIrrDeviceSDL::getScancodeFromKey(const Keycode &key) const
|
||||
{
|
||||
u32 keynum = 0;
|
||||
if (const auto *keycode = std::get_if<EKEY_CODE>(&key)) {
|
||||
if (is_fake_key(*keycode))
|
||||
return *keycode;
|
||||
for (const auto &entry: KeyMap) {
|
||||
if (entry.second == *keycode) {
|
||||
keynum = entry.first;
|
||||
@ -233,7 +244,7 @@ u32 CIrrDeviceSDL::getScancodeFromKey(const Keycode &key) const
|
||||
} else {
|
||||
keynum = std::get<wchar_t>(key);
|
||||
}
|
||||
return SDL_GetScancodeFromKey(keynum);
|
||||
return (u32)SDL_GetScancodeFromKey(keynum);
|
||||
}
|
||||
|
||||
Keycode CIrrDeviceSDL::getKeyFromScancode(const u32 scancode) const
|
||||
|
@ -288,8 +288,8 @@ 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;
|
||||
std::variant<u32, EKEY_CODE> getScancodeFromKey(const Keycode &key) const override;
|
||||
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();
|
||||
|
@ -280,6 +280,13 @@ static const table_key &lookup_scancode(const u32 scancode)
|
||||
lookup_keykey(std::get<irr::EKEY_CODE>(key)) :
|
||||
lookup_keychar(std::get<wchar_t>(key));
|
||||
}
|
||||
|
||||
static const table_key &lookup_scancode(const std::variant<u32, irr::EKEY_CODE> &scancode)
|
||||
{
|
||||
return std::holds_alternative<irr::EKEY_CODE>(scancode) ?
|
||||
lookup_keykey(std::get<irr::EKEY_CODE>(scancode)) :
|
||||
lookup_scancode(std::get<u32>(scancode));
|
||||
}
|
||||
#endif
|
||||
|
||||
KeyPress::KeyPress(std::string_view name)
|
||||
@ -297,18 +304,30 @@ KeyPress::KeyPress(std::string_view name)
|
||||
#endif
|
||||
}
|
||||
|
||||
KeyPress::KeyPress(const irr::SEvent::SKeyInput &in) :
|
||||
KeyPress::KeyPress(const irr::SEvent::SKeyInput &in)
|
||||
#if USE_SDL2
|
||||
scancode(in.SystemKeyCode) {}
|
||||
{
|
||||
if (in.SystemKeyCode)
|
||||
scancode.emplace<u32>(in.SystemKeyCode);
|
||||
else
|
||||
scancode.emplace<irr::EKEY_CODE>(in.Key);
|
||||
}
|
||||
#else
|
||||
Key(in.Key), Char(in.Char ? in.Char : lookup_keykey(in.Key).Char) {}
|
||||
: Key(in.Key), Char(in.Char ? in.Char : lookup_keykey(in.Key).Char) {}
|
||||
#endif
|
||||
|
||||
#if USE_SDL2
|
||||
std::string KeyPress::formatScancode() const
|
||||
{
|
||||
if (auto pv = std::get_if<u32>(&scancode))
|
||||
return *pv == 0 ? "" : "<" + std::to_string(*pv) + ">";
|
||||
return lookup_keykey(std::get<irr::EKEY_CODE>(scancode)).Name;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string KeyPress::sym(const bool force_scancode) const
|
||||
{
|
||||
#if USE_SDL2
|
||||
if (scancode == 0)
|
||||
return "";
|
||||
if (force_scancode)
|
||||
return formatScancode();
|
||||
const auto &name = lookup_scancode(scancode).Name;
|
||||
@ -327,8 +346,7 @@ std::string KeyPress::name() const
|
||||
{
|
||||
#if USE_SDL2
|
||||
const auto &name = lookup_scancode(scancode).LangName;
|
||||
auto table_key = lookup_scancode(scancode);
|
||||
if (!name.empty() || scancode == 0)
|
||||
if (!name.empty())
|
||||
return name;
|
||||
return formatScancode();
|
||||
#else
|
||||
@ -363,7 +381,7 @@ bool KeyPress::loadFromScancode(std::string_view name)
|
||||
const auto code = strtoul(name.data()+1, &p, 10);
|
||||
if (p != name.data() + name.size() - 1)
|
||||
return false;
|
||||
scancode = code;
|
||||
scancode.emplace<u32>(code);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <IEventReceiver.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
|
||||
/* A key press, consisting of a scancode or a keycode */
|
||||
class KeyPress
|
||||
@ -31,10 +32,10 @@ public:
|
||||
u32 getScancode() const
|
||||
{
|
||||
#if USE_SDL2
|
||||
return scancode;
|
||||
#else
|
||||
return 0;
|
||||
if (auto pv = std::get_if<u32>(&scancode))
|
||||
return *pv;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
irr::SEvent toKeyEvent(bool pressedDown = false) const
|
||||
@ -57,7 +58,9 @@ public:
|
||||
operator bool() const
|
||||
{
|
||||
#if USE_SDL2
|
||||
return scancode != 0;
|
||||
return std::holds_alternative<irr::EKEY_CODE>(scancode) ?
|
||||
Keycode::isValid(std::get<irr::EKEY_CODE>(scancode)) :
|
||||
std::get<u32>(scancode) != 0;
|
||||
#else
|
||||
return Char > 0 || Keycode::isValid(Key);
|
||||
#endif
|
||||
@ -68,13 +71,9 @@ public:
|
||||
private:
|
||||
#if USE_SDL2
|
||||
bool loadFromScancode(std::string_view name);
|
||||
std::string formatScancode() const;
|
||||
|
||||
inline std::string formatScancode() const
|
||||
{
|
||||
return "<" + std::to_string(scancode) + ">";
|
||||
}
|
||||
|
||||
u32 scancode = 0;
|
||||
std::variant<u32, irr::EKEY_CODE> scancode = irr::KEY_UNKNOWN;
|
||||
#else
|
||||
irr::EKEY_CODE Key = irr::KEY_KEY_CODES_COUNT;
|
||||
wchar_t Char = L'\0';
|
||||
|
@ -80,7 +80,12 @@ void TestKeycode::testCreateFromString()
|
||||
template<typename ...Args>
|
||||
static u32 toScancode(Args... args)
|
||||
{
|
||||
return RenderingEngine::get_raw_device()->getScancodeFromKey(Keycode(args...));
|
||||
#if USE_SDL2
|
||||
if (const auto &scancode = RenderingEngine::get_raw_device()->getScancodeFromKey(Keycode(args...));
|
||||
const auto &pv = std::get_if<u32>(&scancode))
|
||||
return *pv;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TestKeycode::testCreateFromSKeyInput()
|
||||
|
Loading…
Reference in New Issue
Block a user