X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fclient%2Finputhandler.h;h=3db105c518ecf6d066d1436247b6f558e3f1f21c;hb=7cea688a1c463c5e8caa28bbdb588a6b497a5d7d;hp=c7c29510d21c89134f12ef2475434e63d4581acb;hpb=362323cdc209956a3d35d8ec7ea03ec31b580d88;p=minetest.git diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h index c7c29510d..3db105c51 100644 --- a/src/client/inputhandler.h +++ b/src/client/inputhandler.h @@ -29,6 +29,38 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gui/touchscreengui.h" #endif +class InputHandler; + +/**************************************************************************** + Fast key cache for main game loop + ****************************************************************************/ + +/* This is faster than using getKeySetting with the tradeoff that functions + * using it must make sure that it's initialised before using it and there is + * no error handling (for example bounds checking). This is really intended for + * use only in the main running loop of the client (the_game()) where the faster + * (up to 10x faster) key lookup is an asset. Other parts of the codebase + * (e.g. formspecs) should continue using getKeySetting(). + */ +struct KeyCache +{ + + KeyCache() + { + handler = NULL; + populate(); + populate_nonchanging(); + } + + void populate(); + + // Keys that are not settings dependent + void populate_nonchanging(); + + KeyPress key[KeyType::INTERNAL_ENUM_COUNT]; + InputHandler *handler; +}; + class KeyList : private std::list { typedef std::list super; @@ -112,8 +144,22 @@ class MyEventReceiver : public IEventReceiver return b; } - void listenForKey(const KeyPress &keyCode) { keysListenedFor.set(keyCode); } - void dontListenForKeys() { keysListenedFor.clear(); } + // Checks whether a key was just pressed. State will be cleared + // in the subsequent iteration of Game::processPlayerInteraction + bool WasKeyPressed(const KeyPress &keycode) const { return keyWasPressed[keycode]; } + + // Checks whether a key was just released. State will be cleared + // in the subsequent iteration of Game::processPlayerInteraction + bool WasKeyReleased(const KeyPress &keycode) const { return keyWasReleased[keycode]; } + + void listenForKey(const KeyPress &keyCode) + { + keysListenedFor.set(keyCode); + } + void dontListenForKeys() + { + keysListenedFor.clear(); + } s32 getMouseWheel() { @@ -126,17 +172,20 @@ class MyEventReceiver : public IEventReceiver { keyIsDown.clear(); keyWasDown.clear(); + keyWasPressed.clear(); + keyWasReleased.clear(); - leftclicked = false; - rightclicked = false; - leftreleased = false; - rightreleased = false; + mouse_wheel = 0; + } - left_active = false; - middle_active = false; - right_active = false; + void clearWasKeyPressed() + { + keyWasPressed.clear(); + } - mouse_wheel = 0; + void clearWasKeyReleased() + { + keyWasReleased.clear(); } MyEventReceiver() @@ -146,17 +195,6 @@ class MyEventReceiver : public IEventReceiver #endif } - bool leftclicked = false; - bool rightclicked = false; - bool leftreleased = false; - bool rightreleased = false; - - bool left_active = false; - bool middle_active = false; - bool right_active = false; - - s32 mouse_wheel = 0; - JoystickController *joystick = nullptr; #ifdef HAVE_TOUCHSCREENGUI @@ -164,10 +202,20 @@ class MyEventReceiver : public IEventReceiver #endif private: + s32 mouse_wheel = 0; + // The current state of keys KeyList keyIsDown; - // Whether a key has been pressed or not + + // Like keyIsDown but only reset when that key is read KeyList keyWasDown; + + // Whether a key has just been pressed + KeyList keyWasPressed; + + // Whether a key has just been released + KeyList keyWasReleased; + // List of keys we listen for // TODO perhaps the type of this is not really // performant as KeyList is designed for few but @@ -179,12 +227,30 @@ class MyEventReceiver : public IEventReceiver class InputHandler { public: - InputHandler() = default; + InputHandler() + { + keycache.handler = this; + keycache.populate(); + } virtual ~InputHandler() = default; - virtual bool isKeyDown(const KeyPress &keyCode) = 0; - virtual bool wasKeyDown(const KeyPress &keyCode) = 0; + virtual bool isRandom() const + { + return false; + } + + virtual bool isKeyDown(GameKeyType k) = 0; + virtual bool wasKeyDown(GameKeyType k) = 0; + virtual bool wasKeyPressed(GameKeyType k) = 0; + virtual bool wasKeyReleased(GameKeyType k) = 0; + virtual bool cancelPressed() = 0; + + virtual float getMovementSpeed() = 0; + virtual float getMovementDirection() = 0; + + virtual void clearWasKeyPressed() {} + virtual void clearWasKeyReleased() {} virtual void listenForKey(const KeyPress &keyCode) {} virtual void dontListenForKeys() {} @@ -192,19 +258,6 @@ class InputHandler virtual v2s32 getMousePos() = 0; virtual void setMousePos(s32 x, s32 y) = 0; - virtual bool getLeftState() = 0; - virtual bool getRightState() = 0; - - virtual bool getLeftClicked() = 0; - virtual bool getRightClicked() = 0; - virtual void resetLeftClicked() = 0; - virtual void resetRightClicked() = 0; - - virtual bool getLeftReleased() = 0; - virtual bool getRightReleased() = 0; - virtual void resetLeftReleased() = 0; - virtual void resetRightReleased() = 0; - virtual s32 getMouseWheel() = 0; virtual void step(float dtime) {} @@ -212,6 +265,7 @@ class InputHandler virtual void clear() {} JoystickController joystick; + KeyCache keycache; }; /* Separated input handler @@ -224,91 +278,117 @@ class RealInputHandler : public InputHandler { m_receiver->joystick = &joystick; } - virtual bool isKeyDown(const KeyPress &keyCode) + + virtual ~RealInputHandler() { - return m_receiver->IsKeyDown(keyCode); + m_receiver->joystick = nullptr; } - virtual bool wasKeyDown(const KeyPress &keyCode) + + virtual bool isKeyDown(GameKeyType k) { - return m_receiver->WasKeyDown(keyCode); + return m_receiver->IsKeyDown(keycache.key[k]) || joystick.isKeyDown(k); } - virtual void listenForKey(const KeyPress &keyCode) + virtual bool wasKeyDown(GameKeyType k) { - m_receiver->listenForKey(keyCode); + return m_receiver->WasKeyDown(keycache.key[k]) || joystick.wasKeyDown(k); } - virtual void dontListenForKeys() { m_receiver->dontListenForKeys(); } - virtual v2s32 getMousePos() + virtual bool wasKeyPressed(GameKeyType k) { - if (RenderingEngine::get_raw_device()->getCursorControl()) { - return RenderingEngine::get_raw_device() - ->getCursorControl() - ->getPosition(); - } - - return m_mousepos; + return m_receiver->WasKeyPressed(keycache.key[k]) || joystick.wasKeyPressed(k); + } + virtual bool wasKeyReleased(GameKeyType k) + { + return m_receiver->WasKeyReleased(keycache.key[k]) || joystick.wasKeyReleased(k); } - virtual void setMousePos(s32 x, s32 y) + virtual float getMovementSpeed() { - if (RenderingEngine::get_raw_device()->getCursorControl()) { - RenderingEngine::get_raw_device() - ->getCursorControl() - ->setPosition(x, y); - } else { - m_mousepos = v2s32(x, y); + bool f = m_receiver->IsKeyDown(keycache.key[KeyType::FORWARD]), + b = m_receiver->IsKeyDown(keycache.key[KeyType::BACKWARD]), + l = m_receiver->IsKeyDown(keycache.key[KeyType::LEFT]), + r = m_receiver->IsKeyDown(keycache.key[KeyType::RIGHT]); + if (f || b || l || r) + { + // if contradictory keys pressed, stay still + if (f && b && l && r) + return 0.0f; + else if (f && b && !l && !r) + return 0.0f; + else if (!f && !b && l && r) + return 0.0f; + return 1.0f; // If there is a keyboard event, assume maximum speed } + return joystick.getMovementSpeed(); } - virtual bool getLeftState() + virtual float getMovementDirection() { - return m_receiver->left_active || joystick.isKeyDown(KeyType::MOUSE_L); + float x = 0, z = 0; + + /* Check keyboard for input */ + if (m_receiver->IsKeyDown(keycache.key[KeyType::FORWARD])) + z += 1; + if (m_receiver->IsKeyDown(keycache.key[KeyType::BACKWARD])) + z -= 1; + if (m_receiver->IsKeyDown(keycache.key[KeyType::RIGHT])) + x += 1; + if (m_receiver->IsKeyDown(keycache.key[KeyType::LEFT])) + x -= 1; + + if (x != 0 || z != 0) /* If there is a keyboard event, it takes priority */ + return atan2(x, z); + else + return joystick.getMovementDirection(); } - virtual bool getRightState() + + virtual bool cancelPressed() { - return m_receiver->right_active || joystick.isKeyDown(KeyType::MOUSE_R); + return wasKeyDown(KeyType::ESC) || m_receiver->WasKeyDown(CancelKey); } - virtual bool getLeftClicked() + virtual void clearWasKeyPressed() { - return m_receiver->leftclicked || joystick.getWasKeyDown(KeyType::MOUSE_L); + m_receiver->clearWasKeyPressed(); } - virtual bool getRightClicked() + virtual void clearWasKeyReleased() { - return m_receiver->rightclicked || joystick.getWasKeyDown(KeyType::MOUSE_R); + m_receiver->clearWasKeyReleased(); } - virtual void resetLeftClicked() + virtual void listenForKey(const KeyPress &keyCode) { - m_receiver->leftclicked = false; - joystick.clearWasKeyDown(KeyType::MOUSE_L); - } - virtual void resetRightClicked() { - m_receiver->rightclicked = false; - joystick.clearWasKeyDown(KeyType::MOUSE_R); + m_receiver->listenForKey(keyCode); } - - virtual bool getLeftReleased() + virtual void dontListenForKeys() { - return m_receiver->leftreleased || joystick.wasKeyReleased(KeyType::MOUSE_L); + m_receiver->dontListenForKeys(); } - virtual bool getRightReleased() + + virtual v2s32 getMousePos() { - return m_receiver->rightreleased || joystick.wasKeyReleased(KeyType::MOUSE_R); + auto control = RenderingEngine::get_raw_device()->getCursorControl(); + if (control) { + return control->getPosition(); + } + + return m_mousepos; } - virtual void resetLeftReleased() + virtual void setMousePos(s32 x, s32 y) { - m_receiver->leftreleased = false; - joystick.clearWasKeyReleased(KeyType::MOUSE_L); + auto control = RenderingEngine::get_raw_device()->getCursorControl(); + if (control) { + control->setPosition(x, y); + } else { + m_mousepos = v2s32(x, y); + } } - virtual void resetRightReleased() + + virtual s32 getMouseWheel() { - m_receiver->rightreleased = false; - joystick.clearWasKeyReleased(KeyType::MOUSE_R); + return m_receiver->getMouseWheel(); } - virtual s32 getMouseWheel() { return m_receiver->getMouseWheel(); } - void clear() { joystick.clear(); @@ -325,94 +405,24 @@ class RandomInputHandler : public InputHandler public: RandomInputHandler() = default; - virtual bool isKeyDown(const KeyPress &keyCode) { return keydown[keyCode]; } - virtual bool wasKeyDown(const KeyPress &keyCode) { return false; } + bool isRandom() const + { + return true; + } + + virtual bool isKeyDown(GameKeyType k) { return keydown[keycache.key[k]]; } + virtual bool wasKeyDown(GameKeyType k) { return false; } + virtual bool wasKeyPressed(GameKeyType k) { return false; } + virtual bool wasKeyReleased(GameKeyType k) { return false; } + virtual bool cancelPressed() { return false; } + virtual float getMovementSpeed() { return movementSpeed; } + virtual float getMovementDirection() { return movementDirection; } virtual v2s32 getMousePos() { return mousepos; } virtual void setMousePos(s32 x, s32 y) { mousepos = v2s32(x, y); } - virtual bool getLeftState() { return leftdown; } - virtual bool getRightState() { return rightdown; } - - virtual bool getLeftClicked() { return leftclicked; } - virtual bool getRightClicked() { return rightclicked; } - virtual void resetLeftClicked() { leftclicked = false; } - virtual void resetRightClicked() { rightclicked = false; } - - virtual bool getLeftReleased() { return leftreleased; } - virtual bool getRightReleased() { return rightreleased; } - virtual void resetLeftReleased() { leftreleased = false; } - virtual void resetRightReleased() { rightreleased = false; } - virtual s32 getMouseWheel() { return 0; } - virtual void step(float dtime) - { - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_jump")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_special1")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_forward")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 40); - keydown.toggle(getKeySetting("keymap_left")); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 20); - mousespeed = v2s32(Rand(-20, 20), Rand(-15, 20)); - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 30); - leftdown = !leftdown; - if (leftdown) - leftclicked = true; - if (!leftdown) - leftreleased = true; - } - } - { - static float counter1 = 0; - counter1 -= dtime; - if (counter1 < 0.0) { - counter1 = 0.1 * Rand(1, 15); - rightdown = !rightdown; - if (rightdown) - rightclicked = true; - if (!rightdown) - rightreleased = true; - } - } - mousepos += mousespeed; - } + virtual void step(float dtime); s32 Rand(s32 min, s32 max); @@ -420,10 +430,6 @@ class RandomInputHandler : public InputHandler KeyList keydown; v2s32 mousepos; v2s32 mousespeed; - bool leftdown = false; - bool rightdown = false; - bool leftclicked = false; - bool rightclicked = false; - bool leftreleased = false; - bool rightreleased = false; + float movementSpeed; + float movementDirection; };