--- /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 <ClanLib/Display/input_device.h>
+#include <ClanLib/Display/keys.h>
+
+#include <list>
+
+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 <typename BitEnumType> 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 <typename BitEnumType> 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 <typename BitEnumType> class InputKeyRepeatQueue {
+ private:
+ TimeMS expire;
+
+ typedef InputKeyRepeatEntry<BitEnumType> entry_type;
+
+ std::list<entry_type> list;
+
+ typedef typename std::list<entry_type>::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 <typename BitEnumType, typename BitMaskType> class InputHandler {
+ private:
+ /**
+ * The keyboard that we read input from
+ */
+ CL_InputDevice &keyboard;
+
+ /**
+ * The keymap that we use
+ */
+ InputKeymapEntry<BitEnumType> *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<BitEnumType> 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<BitEnumType> *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<PlayerInputBit, PlayerInput> player;
+
+ /**
+ * Our GuiInput
+ */
+ InputHandler<GuiInputBit, GuiInput> 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 <cassert>
+
+namespace graphics
+{
+
+template <typename BitEnumType, typename BitMaskType>
+void InputHandler<BitEnumType, BitMaskType>::enable (void) {
+ // sanity-check
+ assert(!_enabled);
+
+ // update state
+ _enabled = true;
+}
+
+template <typename BitEnumType, typename BitMaskType>
+void InputHandler<BitEnumType, BitMaskType>::disable (void) {
+ // sanity-check
+ assert(_enabled);
+
+ // update state
+ value = prev_value = 0;
+ _enabled = false;
+
+ // and clear keyrepeat list
+ queue.clear();
+}
+
+
+}
+
+#endif