diff -r 7dddc163489a -r cede5463b845 src/Graphics/Input.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Graphics/Input.hh Thu Jan 22 00:02:53 2009 +0200 @@ -0,0 +1,338 @@ +#ifndef GRAPHICS_INPUT_HH +#define GRAPHICS_INPUT_HH + +#include "../Input.hh" +#include "../Timer.hh" +#include "../Types.hh" + +#include +#include + +#include + +namespace graphics +{ + +/** + * Flags to control input behaviour + */ +enum InputFlagBits { + /** Default */ + + /** + * The bit is not limited, i.e. it is set every time if it's present + */ + INPUT_FLAG_UNLIMITED = 0x0000, + + /** + * The bit is repeat-limited using INPUT_REPEAT_DELAY + */ + INPUT_FLAG_SLOWREPEAT = 0x0001, + + /** + * The bit is repeat-limited using an infinite delay, i.e. you must release the key to trigger it again + */ + INPUT_FLAG_NOREPEAT = 0x0002, +}; + + +/** + * The bits used in the GuiInput bitmask, each represents something handled locally by Graphics. + */ +enum GuiInputBit { + GUI_INPUT_NONE = 0x0000, + + GUI_INPUT_QUIT = 0x0001, + GUI_INPUT_DISPLAY_WEAPON = 0x0002, + GUI_INPUT_DEBUG_PLAYER = 0x0004, + + GUI_INPUT_TOGGLE_FULLSCREEN = 0x0008, +}; + +/** + * Bitmask of InputFlagBits + */ +typedef uint8_t InputFlags; + +/** + * Bitmask for GuiInputBits + * + * @see GuiInputBit + */ +typedef uint16_t GuiInput; + +/** + * Keymap definition struct + */ +template struct InputKeymapEntry { + /** + * The input bit to set if present + */ + BitEnumType input; + + /** + * Flags to use + * + * @see InputFlagBits + */ + InputFlags flags; + + /** + * Up to two keycodes to check + */ + int keycodes[2]; +}; + + +/** + * A InputKeyRepeatQueue entry, this contains the input bit value itself, and then the remaining expire time + */ +template struct InputKeyRepeatEntry { + BitEnumType value; + + /** + * The remaining expire time. If this is zero, it never expires + */ + TimeMS expire; + + public: + InputKeyRepeatEntry (BitEnumType value, TimeMS expire); + + /** + * Since priority_queue always gives the greatest item, the one with the longest expire is the least item + */ + bool operator< (const struct InputKeyRepeatEntry &other); + + /** + * Decrements expire, returning true if it has now expired, false otherwise. Always returns false if expire is + * zero. + */ + bool updateExpired (TimeMS dt); +}; + +/** + * A InputKeyRepeatQueue maintains a list of InputKeyRepeatEntry's, lets you add new input values, find old ones, + * and update the list + */ +template class InputKeyRepeatQueue { + private: + TimeMS expire; + + typedef InputKeyRepeatEntry entry_type; + + std::list list; + + typedef typename std::list::iterator list_iterator; + + public: + /** + * Constructs this queue to contain entries with the given expiry time + */ + InputKeyRepeatQueue (TimeMS expire); + + /** + * Push a new input bit onto the queue. + * + * If expire is true, the bit will automatically expire after our expire time, otherwise, it iwll never expire + * until forget()'d + */ + void push (BitEnumType bit, bool expire = true); + + /** + * Remove any entry for the given bit + */ + void forget (BitEnumType bit); + + /** + * Checks if the given input is in the queue + */ + bool find (BitEnumType bit); + + /** + * Updates the list, removing expired items + */ + void update (TimeMS dt); + + /** + * Clear the queue completely + */ + void clear (void); +}; + +/** + * An InputHandler uses an InputKeymapEntry to maintain a BitMaskType of current inputs + */ +template class InputHandler { + private: + /** + * The keyboard that we read input from + */ + CL_InputDevice &keyboard; + + /** + * The keymap that we use + */ + InputKeymapEntry *keymap; + + /** + * The current bitmask value + */ + BitMaskType value; + + /** + * The previous value, used to detect key-up. This also includes keys that were filtered out + */ + BitMaskType prev_value; + + /** + * How long the bitmask was held... + */ + TimeMS dt; + + /** + * The KeyRepeatQueue + */ + InputKeyRepeatQueue queue; + + /** + * Are we enabled or not? + */ + bool _enabled; + + public: + /** + * Constructs the InputHandler using the given keyboard, keymap and key-repeat expire time. + * + * The InputHandler is initially disabled, and must be enabled using enable() for use. + */ + InputHandler (CL_InputDevice &keyboard, InputKeymapEntry *keymap, TimeMS keyrepeat_expire); + + private: + /** + * Returns true if the keycode is valid, false if not. + * + * A positive keycode requires that the keycode be active, a negative keycode that the keycode be inactive, + * and a zero keycode always returns true. + * + * @param keycode A positive keycode to check that it's set, negative keycode to check that it's not set, or zero + * @returns bool true if positive+set/negavtive+notset/zero, false otherwise + */ + bool checkKeycode (int keycode); + + public: + /** + * Updates the keyrepeat queue + */ + void update (TimeMS dt); + + /** + * Reads the current input mask value and length into mask and dt, and reset ours to zero. + * + * It is an error to attempt to read input while disabled. + * + * @param mask our BitMaskType value is returned using this + * @param dt how long the input was held for + */ + void readValue (BitMaskType &mask, TimeMS &dt); + + /** + * Enables this input handler, collecting bits in value + */ + void enable (void); + + /** + * Disables this input handler, zeroing any state, so that enable() works cleanly + */ + void disable (void); + + /** + * Current enable/disable state + */ + bool enabled (void) const { return _enabled; } +}; + +/** + * Handles reading input from a keyboard and mapping it to PlayerInput/GuiInput bitmasks + */ +class Input { + protected: + /** + * The keyboard device that we use + */ + CL_InputDevice &keyboard; + + /** + * Our update timer + */ + Timer update_timer; + + CL_SlotContainer slots; + + public: + /** + * Our PlayerInput + */ + InputHandler player; + + /** + * Our GuiInput + */ + InputHandler gui; + + public: + /** + * Build the input handler using the given keyboard and the default keymaps + */ + Input (CL_InputDevice &keyboard); + + public: + /** + * Reads the current PlayerInput value via mask, and the length of the input via dt + */ + void readPlayerInput (PlayerInput &mask, TimeMS &dt); + + /** + * Reads the current GuiInput mask and returns it + */ + GuiInput readGuiInput (void); +}; + +} + + + + +/* + * Public template class method definitions + */ +#include + +namespace graphics +{ + +template +void InputHandler::enable (void) { + // sanity-check + assert(!_enabled); + + // update state + _enabled = true; +} + +template +void InputHandler::disable (void) { + // sanity-check + assert(_enabled); + + // update state + value = prev_value = 0; + _enabled = false; + + // and clear keyrepeat list + queue.clear(); +} + + +} + +#endif