src/Graphics/Input.hh
branchnew_graphics
changeset 414 cede5463b845
parent 389 e74c1820fbd2
child 416 38cba347a3a9
equal deleted inserted replaced
413:7dddc163489a 414:cede5463b845
       
     1 #ifndef GRAPHICS_INPUT_HH
       
     2 #define GRAPHICS_INPUT_HH
       
     3 
       
     4 #include "../Input.hh"
       
     5 #include "../Timer.hh"
       
     6 #include "../Types.hh"
       
     7 
       
     8 #include <ClanLib/Display/input_device.h>
       
     9 #include <ClanLib/Display/keys.h>
       
    10 
       
    11 #include <list>
       
    12 
       
    13 namespace graphics
       
    14 {
       
    15 
       
    16 /**
       
    17  * Flags to control input behaviour
       
    18  */
       
    19 enum InputFlagBits {
       
    20     /** Default */
       
    21 
       
    22     /**
       
    23      * The bit is not limited, i.e. it is set every time if it's present
       
    24      */
       
    25     INPUT_FLAG_UNLIMITED    = 0x0000,
       
    26 
       
    27     /**
       
    28      * The bit is repeat-limited using INPUT_REPEAT_DELAY
       
    29      */
       
    30     INPUT_FLAG_SLOWREPEAT   = 0x0001,
       
    31 
       
    32     /**
       
    33      * The bit is repeat-limited using an infinite delay, i.e. you must release the key to trigger it again
       
    34      */
       
    35     INPUT_FLAG_NOREPEAT     = 0x0002,
       
    36 };
       
    37 
       
    38 
       
    39 /**
       
    40  * The bits used in the GuiInput bitmask, each represents something handled locally by Graphics.
       
    41  */
       
    42 enum GuiInputBit {
       
    43     GUI_INPUT_NONE              = 0x0000,
       
    44 
       
    45     GUI_INPUT_QUIT              = 0x0001,
       
    46     GUI_INPUT_DISPLAY_WEAPON    = 0x0002,
       
    47     GUI_INPUT_DEBUG_PLAYER      = 0x0004,
       
    48 
       
    49     GUI_INPUT_TOGGLE_FULLSCREEN = 0x0008,
       
    50 };
       
    51 
       
    52 /**
       
    53  * Bitmask of InputFlagBits
       
    54  */
       
    55 typedef uint8_t InputFlags;
       
    56 
       
    57 /**
       
    58  * Bitmask for GuiInputBits
       
    59  *
       
    60  * @see GuiInputBit
       
    61  */
       
    62 typedef uint16_t GuiInput;
       
    63 
       
    64 /**
       
    65  * Keymap definition struct
       
    66  */
       
    67 template <typename BitEnumType> struct InputKeymapEntry {
       
    68     /**
       
    69      * The input bit to set if present
       
    70      */
       
    71     BitEnumType input;
       
    72 
       
    73     /**
       
    74      * Flags to use
       
    75      *
       
    76      * @see InputFlagBits
       
    77      */
       
    78     InputFlags flags;
       
    79 
       
    80     /**
       
    81      * Up to two keycodes to check
       
    82      */
       
    83     int keycodes[2];
       
    84 };
       
    85 
       
    86 
       
    87 /**
       
    88  * A InputKeyRepeatQueue entry, this contains the input bit value itself, and then the remaining expire time
       
    89  */
       
    90 template <typename BitEnumType> struct InputKeyRepeatEntry {
       
    91         BitEnumType value;
       
    92 
       
    93         /**
       
    94          * The remaining expire time. If this is zero, it never expires
       
    95          */
       
    96         TimeMS expire;
       
    97 
       
    98     public:
       
    99         InputKeyRepeatEntry (BitEnumType value, TimeMS expire);
       
   100         
       
   101         /**
       
   102          * Since priority_queue always gives the greatest item, the one with the longest expire is the least item
       
   103          */
       
   104         bool operator< (const struct InputKeyRepeatEntry &other);
       
   105         
       
   106         /**
       
   107          * Decrements expire, returning true if it has now expired, false otherwise. Always returns false if expire is
       
   108          * zero.
       
   109          */
       
   110         bool updateExpired (TimeMS dt);
       
   111 };
       
   112 
       
   113 /**
       
   114  * A InputKeyRepeatQueue maintains a list of InputKeyRepeatEntry's, lets you add new input values, find old ones,
       
   115  * and update the list
       
   116  */
       
   117 template <typename BitEnumType> class InputKeyRepeatQueue {
       
   118     private:
       
   119         TimeMS expire;
       
   120 
       
   121         typedef InputKeyRepeatEntry<BitEnumType> entry_type;
       
   122 
       
   123         std::list<entry_type> list;
       
   124 
       
   125         typedef typename std::list<entry_type>::iterator list_iterator;
       
   126 
       
   127     public:
       
   128         /**
       
   129          * Constructs this queue to contain entries with the given expiry time
       
   130          */
       
   131         InputKeyRepeatQueue (TimeMS expire);
       
   132         
       
   133         /**
       
   134          * Push a new input bit onto the queue.
       
   135          *
       
   136          * If expire is true, the bit will automatically expire after our expire time, otherwise, it iwll never expire
       
   137          * until forget()'d
       
   138          */
       
   139         void push (BitEnumType bit, bool expire = true);
       
   140 
       
   141         /**
       
   142          * Remove any entry for the given bit
       
   143          */
       
   144         void forget (BitEnumType bit);
       
   145 
       
   146         /**
       
   147          * Checks if the given input is in the queue
       
   148          */
       
   149         bool find (BitEnumType bit);
       
   150         
       
   151         /**
       
   152          * Updates the list, removing expired items
       
   153          */
       
   154         void update (TimeMS dt);
       
   155 
       
   156         /**
       
   157          * Clear the queue completely
       
   158          */
       
   159         void clear (void);
       
   160 };
       
   161 
       
   162 /**
       
   163  * An InputHandler uses an InputKeymapEntry to maintain a BitMaskType of current inputs
       
   164  */
       
   165 template <typename BitEnumType, typename BitMaskType> class InputHandler {
       
   166     private:
       
   167         /**
       
   168          * The keyboard that we read input from
       
   169          */
       
   170         CL_InputDevice &keyboard;
       
   171         
       
   172         /**
       
   173          * The keymap that we use
       
   174          */
       
   175         InputKeymapEntry<BitEnumType> *keymap;
       
   176         
       
   177         /**
       
   178          * The current bitmask value
       
   179          */
       
   180         BitMaskType value;
       
   181 
       
   182         /**
       
   183          * The previous value, used to detect key-up. This also includes keys that were filtered out
       
   184          */
       
   185         BitMaskType prev_value;
       
   186 
       
   187         /**
       
   188          * How long the bitmask was held...
       
   189          */
       
   190         TimeMS dt;
       
   191         
       
   192         /**
       
   193          * The KeyRepeatQueue
       
   194          */
       
   195         InputKeyRepeatQueue<BitEnumType> queue;
       
   196 
       
   197         /**
       
   198          * Are we enabled or not?
       
   199          */
       
   200         bool _enabled;
       
   201     
       
   202     public:
       
   203         /**
       
   204          * Constructs the InputHandler using the given keyboard, keymap and key-repeat expire time.
       
   205          *
       
   206          * The InputHandler is initially disabled, and must be enabled using enable() for use. 
       
   207          */
       
   208         InputHandler (CL_InputDevice &keyboard, InputKeymapEntry<BitEnumType> *keymap, TimeMS keyrepeat_expire);
       
   209     
       
   210     private: 
       
   211         /**
       
   212          * Returns true if the keycode is valid, false if not.
       
   213          *
       
   214          * A positive keycode requires that the keycode be active, a negative keycode that the keycode be inactive,
       
   215          * and a zero keycode always returns true.
       
   216          *
       
   217          * @param keycode A positive keycode to check that it's set, negative keycode to check that it's not set, or zero
       
   218          * @returns bool true if positive+set/negavtive+notset/zero, false otherwise
       
   219          */
       
   220         bool checkKeycode (int keycode);
       
   221     
       
   222     public:
       
   223         /**
       
   224          * Updates the keyrepeat queue
       
   225          */
       
   226         void update (TimeMS dt);
       
   227 
       
   228         /**
       
   229          * Reads the current input mask value and length into mask and dt, and reset ours to zero.
       
   230          *
       
   231          * It is an error to attempt to read input while disabled.
       
   232          *
       
   233          * @param mask our BitMaskType value is returned using this
       
   234          * @param dt how long the input was held for
       
   235          */
       
   236         void readValue (BitMaskType &mask, TimeMS &dt);
       
   237         
       
   238         /**
       
   239          * Enables this input handler, collecting bits in value
       
   240          */
       
   241         void enable (void);
       
   242 
       
   243         /**
       
   244          * Disables this input handler, zeroing any state, so that enable() works cleanly
       
   245          */
       
   246         void disable (void);
       
   247 
       
   248         /**
       
   249          * Current enable/disable state
       
   250          */
       
   251         bool enabled (void) const { return _enabled; }
       
   252 };
       
   253 
       
   254 /**
       
   255  * Handles reading input from a keyboard and mapping it to PlayerInput/GuiInput bitmasks
       
   256  */
       
   257 class Input {
       
   258     protected:
       
   259         /**
       
   260          * The keyboard device that we use
       
   261          */
       
   262         CL_InputDevice &keyboard;
       
   263 
       
   264         /**
       
   265          * Our update timer
       
   266          */
       
   267         Timer update_timer;
       
   268 
       
   269         CL_SlotContainer slots;
       
   270     
       
   271     public:        
       
   272         /**
       
   273          * Our PlayerInput
       
   274          */
       
   275         InputHandler<PlayerInputBit, PlayerInput> player;
       
   276         
       
   277         /**
       
   278          * Our GuiInput
       
   279          */
       
   280         InputHandler<GuiInputBit, GuiInput> gui;
       
   281 
       
   282     public:
       
   283         /**
       
   284          * Build the input handler using the given keyboard and the default keymaps
       
   285          */
       
   286         Input (CL_InputDevice &keyboard);
       
   287 
       
   288     public:
       
   289         /**
       
   290          * Reads the current PlayerInput value via mask, and the length of the input via dt
       
   291          */
       
   292         void readPlayerInput (PlayerInput &mask, TimeMS &dt);
       
   293 
       
   294         /**
       
   295          * Reads the current GuiInput mask and returns it
       
   296          */
       
   297         GuiInput readGuiInput (void);
       
   298 };
       
   299 
       
   300 }
       
   301 
       
   302 
       
   303 
       
   304 
       
   305 /*
       
   306  * Public template class method definitions
       
   307  */
       
   308 #include <cassert>
       
   309 
       
   310 namespace graphics
       
   311 {
       
   312 
       
   313 template <typename BitEnumType, typename BitMaskType> 
       
   314 void InputHandler<BitEnumType, BitMaskType>::enable (void) {
       
   315     // sanity-check
       
   316     assert(!_enabled);
       
   317 
       
   318     // update state
       
   319     _enabled = true;
       
   320 }
       
   321 
       
   322 template <typename BitEnumType, typename BitMaskType> 
       
   323 void InputHandler<BitEnumType, BitMaskType>::disable (void) {
       
   324     // sanity-check
       
   325     assert(_enabled);
       
   326 
       
   327     // update state
       
   328     value = prev_value = 0;
       
   329     _enabled = false;
       
   330 
       
   331     // and clear keyrepeat list
       
   332     queue.clear();
       
   333 }
       
   334        
       
   335 
       
   336 }
       
   337 
       
   338 #endif