Skip to content

Commit

Permalink
Replace MyEventReceiver KeyList with std::unordered_set (#10419)
Browse files Browse the repository at this point in the history
  • Loading branch information
v-rob committed Sep 23, 2020
1 parent 34e3ede commit 787561b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 111 deletions.
48 changes: 26 additions & 22 deletions src/client/inputhandler.cpp
Expand Up @@ -112,23 +112,23 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
// Remember whether each key is down or up // Remember whether each key is down or up
if (event.EventType == irr::EET_KEY_INPUT_EVENT) { if (event.EventType == irr::EET_KEY_INPUT_EVENT) {
const KeyPress &keyCode = event.KeyInput; const KeyPress &keyCode = event.KeyInput;
if (keysListenedFor[keyCode]) { if (keysListenedFor.count(keyCode)) {
// If the key is being held down then the OS may // If the key is being held down then the OS may
// send a continuous stream of keydown events. // send a continuous stream of keydown events.
// In this case, we don't want to let this // In this case, we don't want to let this
// stream reach the application as it will cause // stream reach the application as it will cause
// certain actions to repeat constantly. // certain actions to repeat constantly.
if (event.KeyInput.PressedDown) { if (event.KeyInput.PressedDown) {
if (!IsKeyDown(keyCode)) { if (!IsKeyDown(keyCode)) {
keyWasDown.set(keyCode); keyWasDown.insert(keyCode);
keyWasPressed.set(keyCode); keyWasPressed.insert(keyCode);
} }
keyIsDown.set(keyCode); keyIsDown.insert(keyCode);
} else { } else {
if (IsKeyDown(keyCode)) if (IsKeyDown(keyCode))
keyWasReleased.set(keyCode); keyWasReleased.insert(keyCode);


keyIsDown.unset(keyCode); keyIsDown.erase(keyCode);
} }


return true; return true;
Expand All @@ -153,36 +153,36 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
switch (event.MouseInput.Event) { switch (event.MouseInput.Event) {
case EMIE_LMOUSE_PRESSED_DOWN: case EMIE_LMOUSE_PRESSED_DOWN:
key = "KEY_LBUTTON"; key = "KEY_LBUTTON";
keyIsDown.set(key); keyIsDown.insert(key);
keyWasDown.set(key); keyWasDown.insert(key);
keyWasPressed.set(key); keyWasPressed.insert(key);
break; break;
case EMIE_MMOUSE_PRESSED_DOWN: case EMIE_MMOUSE_PRESSED_DOWN:
key = "KEY_MBUTTON"; key = "KEY_MBUTTON";
keyIsDown.set(key); keyIsDown.insert(key);
keyWasDown.set(key); keyWasDown.insert(key);
keyWasPressed.set(key); keyWasPressed.insert(key);
break; break;
case EMIE_RMOUSE_PRESSED_DOWN: case EMIE_RMOUSE_PRESSED_DOWN:
key = "KEY_RBUTTON"; key = "KEY_RBUTTON";
keyIsDown.set(key); keyIsDown.insert(key);
keyWasDown.set(key); keyWasDown.insert(key);
keyWasPressed.set(key); keyWasPressed.insert(key);
break; break;
case EMIE_LMOUSE_LEFT_UP: case EMIE_LMOUSE_LEFT_UP:
key = "KEY_LBUTTON"; key = "KEY_LBUTTON";
keyIsDown.unset(key); keyIsDown.erase(key);
keyWasReleased.set(key); keyWasReleased.insert(key);
break; break;
case EMIE_MMOUSE_LEFT_UP: case EMIE_MMOUSE_LEFT_UP:
key = "KEY_MBUTTON"; key = "KEY_MBUTTON";
keyIsDown.unset(key); keyIsDown.erase(key);
keyWasReleased.set(key); keyWasReleased.insert(key);
break; break;
case EMIE_RMOUSE_LEFT_UP: case EMIE_RMOUSE_LEFT_UP:
key = "KEY_RBUTTON"; key = "KEY_RBUTTON";
keyIsDown.unset(key); keyIsDown.erase(key);
keyWasReleased.set(key); keyWasReleased.insert(key);
break; break;
case EMIE_MOUSE_WHEEL: case EMIE_MOUSE_WHEEL:
mouse_wheel += event.MouseInput.Wheel; mouse_wheel += event.MouseInput.Wheel;
Expand Down Expand Up @@ -235,7 +235,11 @@ void RandomInputHandler::step(float dtime)
i.counter -= dtime; i.counter -= dtime;
if (i.counter < 0.0) { if (i.counter < 0.0) {
i.counter = 0.1 * Rand(1, i.time_max); i.counter = 0.1 * Rand(1, i.time_max);
keydown.toggle(getKeySetting(i.key.c_str())); KeyPress k = getKeySetting(i.key.c_str());
if (keydown.count(k))
keydown.erase(k);
else
keydown.insert(k);
} }
} }
{ {
Expand Down
108 changes: 19 additions & 89 deletions src/client/inputhandler.h
Expand Up @@ -21,9 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,


#include "irrlichttypes_extrabloated.h" #include "irrlichttypes_extrabloated.h"
#include "joystick_controller.h" #include "joystick_controller.h"
#include <list>
#include "keycode.h" #include "keycode.h"
#include "renderingengine.h" #include "renderingengine.h"
#include <unordered_set>


#ifdef HAVE_TOUCHSCREENGUI #ifdef HAVE_TOUCHSCREENGUI
#include "gui/touchscreengui.h" #include "gui/touchscreengui.h"
Expand Down Expand Up @@ -61,98 +61,32 @@ struct KeyCache
InputHandler *handler; InputHandler *handler;
}; };


class KeyList : private std::list<KeyPress>
{
typedef std::list<KeyPress> super;
typedef super::iterator iterator;
typedef super::const_iterator const_iterator;

virtual const_iterator find(const KeyPress &key) const
{
const_iterator f(begin());
const_iterator e(end());

while (f != e) {
if (*f == key)
return f;

++f;
}

return e;
}

virtual iterator find(const KeyPress &key)
{
iterator f(begin());
iterator e(end());

while (f != e) {
if (*f == key)
return f;

++f;
}

return e;
}

public:
void clear() { super::clear(); }

void set(const KeyPress &key)
{
if (find(key) == end())
push_back(key);
}

void unset(const KeyPress &key)
{
iterator p(find(key));

if (p != end())
erase(p);
}

void toggle(const KeyPress &key)
{
iterator p(this->find(key));

if (p != end())
erase(p);
else
push_back(key);
}

bool operator[](const KeyPress &key) const { return find(key) != end(); }
};

class MyEventReceiver : public IEventReceiver class MyEventReceiver : public IEventReceiver
{ {
public: public:
// This is the one method that we have to implement // This is the one method that we have to implement
virtual bool OnEvent(const SEvent &event); virtual bool OnEvent(const SEvent &event);


bool IsKeyDown(const KeyPress &keyCode) const { return keyIsDown[keyCode]; } bool IsKeyDown(const KeyPress &keyCode) const { return keyIsDown.count(keyCode); }


// Checks whether a key was down and resets the state // Checks whether a key was down and resets the state
bool WasKeyDown(const KeyPress &keyCode) bool WasKeyDown(const KeyPress &keyCode)
{ {
bool b = keyWasDown[keyCode]; bool b = keyWasDown.count(keyCode);
if (b) if (b)
keyWasDown.unset(keyCode); keyWasDown.erase(keyCode);
return b; return b;
} }


// Checks whether a key was just pressed. State will be cleared // Checks whether a key was just pressed. State will be cleared
// in the subsequent iteration of Game::processPlayerInteraction // in the subsequent iteration of Game::processPlayerInteraction
bool WasKeyPressed(const KeyPress &keycode) const { return keyWasPressed[keycode]; } bool WasKeyPressed(const KeyPress &keycode) const { return keyWasPressed.count(keycode); }


// Checks whether a key was just released. State will be cleared // Checks whether a key was just released. State will be cleared
// in the subsequent iteration of Game::processPlayerInteraction // in the subsequent iteration of Game::processPlayerInteraction
bool WasKeyReleased(const KeyPress &keycode) const { return keyWasReleased[keycode]; } bool WasKeyReleased(const KeyPress &keycode) const { return keyWasReleased.count(keycode); }


void listenForKey(const KeyPress &keyCode) { keysListenedFor.set(keyCode); } void listenForKey(const KeyPress &keyCode) { keysListenedFor.insert(keyCode); }
void dontListenForKeys() { keysListenedFor.clear(); } void dontListenForKeys() { keysListenedFor.clear(); }


s32 getMouseWheel() s32 getMouseWheel()
Expand Down Expand Up @@ -198,24 +132,20 @@ class MyEventReceiver : public IEventReceiver
#endif #endif


private: private:
// The current state of keys //! The current state of keys
KeyList keyIsDown; std::unordered_set<KeyPress> keyIsDown;


// Whether a key was down //! Whether a key was down
KeyList keyWasDown; std::unordered_set<KeyPress> keyWasDown;


// Whether a key has just been pressed //! Whether a key has just been pressed
KeyList keyWasPressed; std::unordered_set<KeyPress> keyWasPressed;


// Whether a key has just been released //! Whether a key has just been released
KeyList keyWasReleased; std::unordered_set<KeyPress> keyWasReleased;


// List of keys we listen for //! List of keys we listen for
// TODO perhaps the type of this is not really std::unordered_set<KeyPress> keysListenedFor;
// performant as KeyList is designed for few but
// often changing keys, and keysListenedFor is expected
// to change seldomly but contain lots of keys.
KeyList keysListenedFor;
}; };


class InputHandler class InputHandler
Expand Down Expand Up @@ -347,7 +277,7 @@ class RandomInputHandler : public InputHandler
return true; return true;
} }


virtual bool isKeyDown(GameKeyType k) { return keydown[keycache.key[k]]; } virtual bool isKeyDown(GameKeyType k) { return keydown.count(keycache.key[k]); }
virtual bool wasKeyDown(GameKeyType k) { return false; } virtual bool wasKeyDown(GameKeyType k) { return false; }
virtual bool wasKeyPressed(GameKeyType k) { return false; } virtual bool wasKeyPressed(GameKeyType k) { return false; }
virtual bool wasKeyReleased(GameKeyType k) { return false; } virtual bool wasKeyReleased(GameKeyType k) { return false; }
Expand All @@ -362,7 +292,7 @@ class RandomInputHandler : public InputHandler
s32 Rand(s32 min, s32 max); s32 Rand(s32 min, s32 max);


private: private:
KeyList keydown; std::unordered_set<KeyPress> keydown;
v2s32 mousepos; v2s32 mousepos;
v2s32 mousespeed; v2s32 mousespeed;
}; };
19 changes: 19 additions & 0 deletions src/client/keycode.h
Expand Up @@ -24,12 +24,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <IEventReceiver.h> #include <IEventReceiver.h>
#include <string> #include <string>


class KeyPress;
namespace std
{
template <> struct hash<KeyPress>;
}

/* A key press, consisting of either an Irrlicht keycode /* A key press, consisting of either an Irrlicht keycode
or an actual char */ or an actual char */


class KeyPress class KeyPress
{ {
public: public:
friend struct std::hash<KeyPress>;

KeyPress() = default; KeyPress() = default;


KeyPress(const char *name); KeyPress(const char *name);
Expand All @@ -55,6 +63,17 @@ class KeyPress
std::string m_name = ""; std::string m_name = "";
}; };


namespace std
{
template <> struct hash<KeyPress>
{
size_t operator()(const KeyPress &key) const
{
return key.Key;
}
};
}

extern const KeyPress EscapeKey; extern const KeyPress EscapeKey;
extern const KeyPress CancelKey; extern const KeyPress CancelKey;


Expand Down

0 comments on commit 787561b

Please sign in to comment.