port Input to new Graphics, still a bit hacky, but everything seems to work now new_graphics
authorTero Marttila <terom@fixme.fi>
Thu, 22 Jan 2009 00:02:53 +0200
branchnew_graphics
changeset 414 cede5463b845
parent 413 7dddc163489a
child 415 c1069d23890b
port Input to new Graphics, still a bit hacky, but everything seems to work now
src/GameState.hh
src/Graphics/Display.cc
src/Graphics/Display.hh
src/Graphics/GameView.cc
src/Graphics/GameView.hh
src/Graphics/Graphics.cc
src/Graphics/Graphics.hh
src/Graphics/Input.cc
src/Graphics/Input.hh
src/Input.cc
src/Input.hh
src/Player.hh
--- a/src/GameState.hh	Wed Jan 21 23:25:29 2009 +0200
+++ b/src/GameState.hh	Thu Jan 22 00:02:53 2009 +0200
@@ -4,10 +4,9 @@
 class GameState;
 
 #include "PhysicsWorld.hh"
+#include "Terrain.hh"
 #include "Player.hh"
 #include "Projectile.hh"
-#include "Rope.hh"
-#include "Input.hh"
 #include "Config.hh"
 
 #include "Graphics/Drawable.hh"
--- a/src/Graphics/Display.cc	Wed Jan 21 23:25:29 2009 +0200
+++ b/src/Graphics/Display.cc	Thu Jan 22 00:02:53 2009 +0200
@@ -60,7 +60,7 @@
         view->resize(PixelArea(0, 0, get_width(), get_height()));
 }
 
-void Display::toggle_fullscreen (void) {
+void Display::toggleFullscreen (void) {
     if (is_fullscreen()) {
         // enter windowed mode
         set_windowed();
--- a/src/Graphics/Display.hh	Wed Jan 21 23:25:29 2009 +0200
+++ b/src/Graphics/Display.hh	Thu Jan 22 00:02:53 2009 +0200
@@ -92,7 +92,7 @@
     /**
      * Shift back and forth between fullscreen and windowed mode, retaining resolutions
      */
-    void toggle_fullscreen (void);
+    void toggleFullscreen (void);
 
 private:
     /**
--- a/src/Graphics/GameView.cc	Wed Jan 21 23:25:29 2009 +0200
+++ b/src/Graphics/GameView.cc	Thu Jan 22 00:02:53 2009 +0200
@@ -18,6 +18,9 @@
 
     // insert message
     message_view.add_message(CL_Color::white, "Hello World!");
+
+    // enable GUI input
+    graphics->input.gui.enable();
 }
 
 void GameView::setPlayer (LocalPlayer *player) {
@@ -28,8 +31,37 @@
 
     // build the info_view as well
     info_view = new PlayerInfoView(getInfoViewArea(), player);
+
+    // enable player input
+    graphics->input.player.enable();
 }
 
+void GameView::handleInput (GuiInput flags, TimeMS dt) {
+    // ignore timing info
+    (void) dt;
+
+    // update our flags
+    this->flags = flags;
+
+    // quit?
+    if (flags & GUI_INPUT_QUIT) {
+        graphics->engine.stop();
+        return;
+    }
+
+    // dump player debug info on stderr
+    if ((flags & GUI_INPUT_DEBUG_PLAYER) && player) {
+        player->printDebugInfo();
+
+        message_view.add_message(CL_Color::green, "...");
+    }
+
+    // toggle fullscreen?
+    if (flags & GUI_INPUT_TOGGLE_FULLSCREEN)
+        graphics->display.toggleFullscreen();
+}
+
+
 /*
  * Helper function for Camera
  */
@@ -49,6 +81,19 @@
 
 void GameView::draw (Display &display) {
     CL_GraphicContext *gc = display.get_gc();
+    
+    // XXX: these should not be done from here
+    handleInput(graphics->input.readGuiInput(), 0);
+    
+    // XXX: this should /really/ be somewhere else
+    if (player) {
+        PlayerInput input;
+        TimeMS dt;
+
+        graphics->input.readPlayerInput(input, dt);
+
+        player->handleInput(input, dt);
+    }
 
     // calculate camera
     PixelCoordinate camera(0, 0);
--- a/src/Graphics/GameView.hh	Wed Jan 21 23:25:29 2009 +0200
+++ b/src/Graphics/GameView.hh	Thu Jan 22 00:02:53 2009 +0200
@@ -4,15 +4,17 @@
 #include "Drawable.hh"
 #include "PlayerInfoView.hh"
 #include "MessageView.hh"
+#include "Input.hh"
 #include "../GameState.hh"
 
-#include "../Input.hh"
 
 namespace graphics
 {
 
 /**
- * This is the main in-game view, which is what the player sees when they are playing
+ * This is the main in-game view, which is what the player sees when they are playing.
+ *
+ * This enables graphics->input.gui/player
  */    
 class GameView : public View {
 protected:
@@ -63,6 +65,11 @@
         return PixelArea(400, area.bottom - 100, area.right, area.bottom);
     }
 
+    /**
+     * Handle GUI input
+     */
+    void handleInput (GuiInput flags, TimeMS dt);
+
 public:    
     
     /**
--- a/src/Graphics/Graphics.cc	Wed Jan 21 23:25:29 2009 +0200
+++ b/src/Graphics/Graphics.cc	Thu Jan 22 00:02:53 2009 +0200
@@ -10,8 +10,11 @@
 Graphics *graphics = NULL;
 
 Graphics::Graphics (Engine &engine, CL_ResourceManager &resources, const DisplayConfig &display_config) :
+    engine(engine), display(display_config), 
     // display must be set up before fonts, due to implicit CL_DisplayWindow
-    engine(engine), display(display_config), fonts(resources)
+    fonts(resources), 
+    // get the InputContext from display
+    input(display.get_ic()->get_keyboard())
 {
     assert(!graphics);
 
--- a/src/Graphics/Graphics.hh	Wed Jan 21 23:25:29 2009 +0200
+++ b/src/Graphics/Graphics.hh	Thu Jan 22 00:02:53 2009 +0200
@@ -11,6 +11,7 @@
 #include "../Engine.hh"
 #include "Display.hh"
 #include "FontManager.hh"
+#include "Input.hh"
 #include "GameView.hh"
 
 namespace graphics
@@ -35,6 +36,13 @@
      * For loading fonts
      */
     FontManager fonts;
+
+    /**
+     * Input handling
+     *
+     * XXX: move Input class into this?
+     */
+    Input input;
    
     /**
      * Initialize the graphics subsystem
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Graphics/Input.cc	Thu Jan 22 00:02:53 2009 +0200
@@ -0,0 +1,246 @@
+
+#include "Input.hh"
+#include "../Error.hh"
+#include "../Config.hh"
+
+#include <cassert>
+
+namespace graphics
+{
+
+InputKeymapEntry<PlayerInputBit> INPUT_PLAYER_KEYMAP[] = {
+    {   INPUT_AIM_UP,       INPUT_FLAG_UNLIMITED,   { -CL_KEY_ENTER,    CL_KEY_UP       } },
+    {   INPUT_AIM_DOWN,     INPUT_FLAG_UNLIMITED,   { -CL_KEY_ENTER,    CL_KEY_DOWN     } },
+    {   INPUT_MOVE_LEFT,    INPUT_FLAG_UNLIMITED,   { -CL_KEY_ENTER,    CL_KEY_LEFT     } },
+    {   INPUT_MOVE_RIGHT,   INPUT_FLAG_UNLIMITED,   { -CL_KEY_ENTER,    CL_KEY_RIGHT    } },
+    {   INPUT_JUMP,         INPUT_FLAG_SLOWREPEAT,  { -CL_KEY_ENTER,    CL_KEY_RSHIFT   } },
+    {   INPUT_DIG,          INPUT_FLAG_NOREPEAT,    { CL_KEY_LEFT,      CL_KEY_RIGHT    } },
+    {   INPUT_SHOOT,        INPUT_FLAG_UNLIMITED,   { CL_KEY_RCONTROL,  0               } },
+    {   INPUT_CHANGE_PREV,  INPUT_FLAG_SLOWREPEAT,  { CL_KEY_ENTER,     CL_KEY_LEFT     } },
+    {   INPUT_CHANGE_NEXT,  INPUT_FLAG_SLOWREPEAT,  { CL_KEY_ENTER,     CL_KEY_RIGHT    } },
+    {   INPUT_ROPE,         INPUT_FLAG_NOREPEAT,    { CL_KEY_ENTER,     CL_KEY_RSHIFT   } },
+    {   INPUT_UNROPE,       INPUT_FLAG_SLOWREPEAT,  { -CL_KEY_ENTER,    CL_KEY_RSHIFT   } },
+    {   INPUT_ROPE_UP,      INPUT_FLAG_UNLIMITED,   { CL_KEY_ENTER,     CL_KEY_UP       } },
+    {   INPUT_ROPE_DOWN,    INPUT_FLAG_UNLIMITED,   { CL_KEY_ENTER,     CL_KEY_DOWN     } },
+    {   INPUT_SUICIDE,      INPUT_FLAG_NOREPEAT,    { CL_KEY_LCONTROL,  CL_KEY_K        } },
+    {   INPUT_NONE,         0,                      { 0,                0               } }
+};
+
+InputKeymapEntry<GuiInputBit> INPUT_GUI_KEYMAP[] = {
+    {   GUI_INPUT_QUIT,                 0,                  { CL_KEY_ESCAPE,    0               } },
+    {   GUI_INPUT_DISPLAY_WEAPON,       0,                  { CL_KEY_ENTER,     0               } },
+    {   GUI_INPUT_DEBUG_PLAYER,         0,                  { CL_KEY_I,         0               } },
+    {   GUI_INPUT_TOGGLE_FULLSCREEN,    INPUT_FLAG_NOREPEAT,{ CL_KEY_LCONTROL,  CL_KEY_F        } },
+    {   GUI_INPUT_NONE,                 0,                  { 0,                0,              } }
+};
+
+/*
+ * InputKeyRepeatEntry
+ */
+template <typename BitEnumType> 
+InputKeyRepeatEntry<BitEnumType>::InputKeyRepeatEntry (BitEnumType value, TimeMS expire) : 
+    value(value), expire(expire) 
+{
+
+}
+
+template <typename BitEnumType> 
+bool InputKeyRepeatEntry<BitEnumType>::operator< (const struct InputKeyRepeatEntry &other) {
+    return other.expire > expire;
+}
+
+template <typename BitEnumType> 
+bool InputKeyRepeatEntry<BitEnumType>::updateExpired (TimeMS dt) {
+    if (expire == 0)
+        return false;
+
+    expire -= dt;
+
+    return (expire <= 0);
+}
+
+/*
+ * InputKeyRepeatQueue
+ */
+template <typename BitEnumType> 
+InputKeyRepeatQueue<BitEnumType>::InputKeyRepeatQueue (TimeMS expire) :
+    expire(expire)
+{
+
+}
+
+template <typename BitEnumType> 
+void InputKeyRepeatQueue<BitEnumType>::push (BitEnumType bit, bool expire) {
+    list.push_back(InputKeyRepeatEntry<BitEnumType>(bit, expire ? this->expire : 0));
+}
+
+template <typename BitEnumType> 
+void InputKeyRepeatQueue<BitEnumType>::forget (BitEnumType bit) {
+    // go through the list, looking for it
+    for (list_iterator it = list.begin(); it != list.end(); it++) {
+        if (it->value == bit) {
+            // found, erase it and return
+            list.erase(it);
+            
+            return;
+        }
+    }
+}
+
+template <typename BitEnumType> 
+bool InputKeyRepeatQueue<BitEnumType>::find (BitEnumType bit) {
+    for (list_iterator it = list.begin(); it != list.end(); it++) {
+        if (it->value == bit)
+            return true;
+    }
+
+    return false;
+}
+
+template <typename BitEnumType> 
+void InputKeyRepeatQueue<BitEnumType>::update (TimeMS dt) {
+    list_iterator it = list.begin();
+    
+    // go through each entry, updateExpired and remove if expired
+    while (it != list.end()) {
+        if (it->updateExpired(dt))
+            it = list.erase(it);
+        else
+            it++;
+    }
+}
+
+template <typename BitEnumType> 
+void InputKeyRepeatQueue<BitEnumType>::clear (void) {
+    // just clear our list of events
+    list.clear();
+}
+
+/*
+ * InputHandler
+ */
+template <typename BitEnumType, typename BitMaskType> 
+InputHandler<BitEnumType, BitMaskType>::InputHandler (CL_InputDevice &keyboard, InputKeymapEntry<BitEnumType> *keymap, TimeMS keyrepeat_expire) :
+    keyboard(keyboard), 
+    keymap(keymap), 
+    value(0), 
+    prev_value(0),
+    dt(0),
+    queue(keyrepeat_expire),
+    _enabled(false)
+{
+
+}
+
+template <typename BitEnumType, typename BitMaskType> 
+bool InputHandler<BitEnumType, BitMaskType>::checkKeycode (int keycode) {
+    if (keycode > 0)
+        return keyboard.get_keycode(keycode);
+
+    else if (keycode < 0)
+        return !keyboard.get_keycode(-keycode);
+
+    else // == 0
+        return true;
+}
+ 
+template <typename BitEnumType, typename BitMaskType> 
+void InputHandler<BitEnumType, BitMaskType>::update (TimeMS dt) {
+    // ignore if not enabled
+    if (!_enabled)
+        return;
+
+    // all bits that are held down, even those ignored
+    BitMaskType raw_value = 0;
+
+    // update the key-repeat queue
+    queue.update(dt);
+
+    // then go through the keymap
+    for (InputKeymapEntry<BitEnumType> *e = keymap; e->input != 0; e++) {
+        // check if we've got the correct keycodes
+        if (checkKeycode(e->keycodes[0]) && checkKeycode(e->keycodes[1])) {
+            // set raw_value
+            raw_value |= e->input;
+
+            if (e->flags & INPUT_FLAG_SLOWREPEAT) {
+                // repeat, but slowly
+                if (!(prev_value & e->input)) {
+                    // we've released the key earlier, move it to the back of the queue
+                    queue.forget(e->input);
+                    queue.push(e->input);
+
+                } else if (queue.find(e->input)) {
+                    // it's still in the queue, so ignore, but set it in ignore_value
+                    continue;
+
+                } else {
+                    // ok, but add it to the queue
+                    queue.push(e->input);
+                }
+
+            } else if (e->flags & INPUT_FLAG_NOREPEAT) {
+                // do not repeat at all
+                if (prev_value & e->input) {
+                    // ignore repeats
+                    continue;
+                }
+            }
+
+            // set bit in masks
+            this->value |= e->input;
+        }
+    }
+
+    // update prev_value, also adding ignored values
+    prev_value = raw_value;
+
+    // then increment our dt
+    this->dt += dt;
+}
+ 
+template <typename BitEnumType, typename BitMaskType> 
+void InputHandler<BitEnumType, BitMaskType>::readValue (BitMaskType &mask, TimeMS &dt) {
+    // throw exception if disabled
+    if (!_enabled)
+        throw Error("InputHandler is disabled");
+
+    // copy to args
+    mask = this->value;
+    dt = this->dt;
+
+    this->value = 0;
+    this->dt = 0;
+}
+       
+/**
+ * Input
+ */
+Input::Input (CL_InputDevice &keyboard) :
+    keyboard(keyboard),
+    update_timer(INPUT_POLL_INTERVAL),
+    player(keyboard, INPUT_PLAYER_KEYMAP, INPUT_REPEAT_DELAY),
+    gui(keyboard, INPUT_GUI_KEYMAP, INPUT_REPEAT_DELAY)
+{
+    // connect timer 
+    slots.connect(update_timer.sig_tick(), &player, &InputHandler<PlayerInputBit, PlayerInput>::update);
+    slots.connect(update_timer.sig_tick(), &gui, &InputHandler<GuiInputBit, GuiInput>::update);
+
+    // enable timer
+    update_timer.start();
+}
+
+void Input::readPlayerInput (PlayerInput &mask, TimeMS &dt) {
+    player.readValue(mask, dt);
+}
+
+GuiInput Input::readGuiInput (void) {
+    GuiInput mask;
+    TimeMS dt;
+
+    gui.readValue(mask, dt);
+
+    return mask;
+}
+
+}
--- /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
--- a/src/Input.cc	Wed Jan 21 23:25:29 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,225 +0,0 @@
-
-#include "Input.hh"
-#include "Engine.hh"
-#include "Config.hh"
-
-InputKeymapEntry<PlayerInputBit> INPUT_PLAYER_KEYMAP[] = {
-    {   INPUT_AIM_UP,       INPUT_FLAG_UNLIMITED,   { -CL_KEY_ENTER,    CL_KEY_UP       } },
-    {   INPUT_AIM_DOWN,     INPUT_FLAG_UNLIMITED,   { -CL_KEY_ENTER,    CL_KEY_DOWN     } },
-    {   INPUT_MOVE_LEFT,    INPUT_FLAG_UNLIMITED,   { -CL_KEY_ENTER,    CL_KEY_LEFT     } },
-    {   INPUT_MOVE_RIGHT,   INPUT_FLAG_UNLIMITED,   { -CL_KEY_ENTER,    CL_KEY_RIGHT    } },
-    {   INPUT_JUMP,         INPUT_FLAG_SLOWREPEAT,  { -CL_KEY_ENTER,    CL_KEY_RSHIFT   } },
-    {   INPUT_DIG,          INPUT_FLAG_NOREPEAT,    { CL_KEY_LEFT,      CL_KEY_RIGHT    } },
-    {   INPUT_SHOOT,        INPUT_FLAG_UNLIMITED,   { CL_KEY_RCONTROL,  0               } },
-    {   INPUT_CHANGE_PREV,  INPUT_FLAG_SLOWREPEAT,  { CL_KEY_ENTER,     CL_KEY_LEFT     } },
-    {   INPUT_CHANGE_NEXT,  INPUT_FLAG_SLOWREPEAT,  { CL_KEY_ENTER,     CL_KEY_RIGHT    } },
-    {   INPUT_ROPE,         INPUT_FLAG_NOREPEAT,    { CL_KEY_ENTER,     CL_KEY_RSHIFT   } },
-    {   INPUT_UNROPE,       INPUT_FLAG_SLOWREPEAT,  { -CL_KEY_ENTER,    CL_KEY_RSHIFT   } },
-    {   INPUT_ROPE_UP,      INPUT_FLAG_UNLIMITED,   { CL_KEY_ENTER,     CL_KEY_UP       } },
-    {   INPUT_ROPE_DOWN,    INPUT_FLAG_UNLIMITED,   { CL_KEY_ENTER,     CL_KEY_DOWN     } },
-    {   INPUT_SUICIDE,      INPUT_FLAG_NOREPEAT,    { CL_KEY_LCONTROL,  CL_KEY_K        } },
-    {   INPUT_NONE,         0,                      { 0,                0               } }
-};
-
-InputKeymapEntry<GuiInputBit> INPUT_GUI_KEYMAP[] = {
-    {   GUI_INPUT_QUIT,                 0,                  { CL_KEY_ESCAPE,    0               } },
-    {   GUI_INPUT_DISPLAY_WEAPON,       0,                  { CL_KEY_ENTER,     0               } },
-    {   GUI_INPUT_DEBUG_PLAYER,         0,                  { CL_KEY_I,         0               } },
-    {   GUI_INPUT_TOGGLE_FULLSCREEN,    INPUT_FLAG_NOREPEAT,{ CL_KEY_LCONTROL,  CL_KEY_F        } },
-    {   GUI_INPUT_NONE,                 0,                  { 0,                0,              } }
-};
-
-/*
- * InputKeyRepeatEntry
- */
-template <typename BitEnumType> 
-InputKeyRepeatEntry<BitEnumType>::InputKeyRepeatEntry (BitEnumType value, TimeMS expire) : 
-    value(value), expire(expire) 
-{
-
-}
-
-template <typename BitEnumType> 
-bool InputKeyRepeatEntry<BitEnumType>::operator< (const struct InputKeyRepeatEntry &other) {
-    return other.expire > expire;
-}
-
-template <typename BitEnumType> 
-bool InputKeyRepeatEntry<BitEnumType>::updateExpired (TimeMS dt) {
-    if (expire == 0)
-        return false;
-
-    expire -= dt;
-
-    return (expire <= 0);
-}
-
-/*
- * InputKeyRepeatQueue
- */
-template <typename BitEnumType> 
-InputKeyRepeatQueue<BitEnumType>::InputKeyRepeatQueue (TimeMS expire) :
-    expire(expire)
-{
-
-}
-
-template <typename BitEnumType> 
-void InputKeyRepeatQueue<BitEnumType>::push (BitEnumType bit, bool expire) {
-    list.push_back(InputKeyRepeatEntry<BitEnumType>(bit, expire ? this->expire : 0));
-}
-
-template <typename BitEnumType> 
-void InputKeyRepeatQueue<BitEnumType>::forget (BitEnumType bit) {
-    // go through the list, looking for it
-    for (list_iterator it = list.begin(); it != list.end(); it++) {
-        if (it->value == bit) {
-            // found, erase it and return
-            list.erase(it);
-            
-            return;
-        }
-    }
-}
-
-template <typename BitEnumType> 
-bool InputKeyRepeatQueue<BitEnumType>::find (BitEnumType bit) {
-    for (list_iterator it = list.begin(); it != list.end(); it++) {
-        if (it->value == bit)
-            return true;
-    }
-
-    return false;
-}
-
-template <typename BitEnumType> 
-void InputKeyRepeatQueue<BitEnumType>::update (TimeMS dt) {
-    list_iterator it = list.begin();
-    
-    // go through each entry, updateExpired and remove if expired
-    while (it != list.end()) {
-        if (it->updateExpired(dt))
-            it = list.erase(it);
-        else
-            it++;
-    }
-}
-
-/*
- * InputHandler
- */
-template <typename BitEnumType, typename BitMaskType> 
-InputHandler<BitEnumType, BitMaskType>::InputHandler (CL_InputDevice &keyboard, InputKeymapEntry<BitEnumType> *keymap, TimeMS keyrepeat_expire) :
-    keyboard(keyboard), 
-    keymap(keymap), 
-    value(0), 
-    prev_value(0),
-    dt(0),
-    queue(keyrepeat_expire)
-{
-
-}
-
-template <typename BitEnumType, typename BitMaskType> 
-bool InputHandler<BitEnumType, BitMaskType>::checkKeycode (int keycode) {
-    if (keycode > 0)
-        return keyboard.get_keycode(keycode);
-
-    else if (keycode < 0)
-        return !keyboard.get_keycode(-keycode);
-
-    else // == 0
-        return true;
-}
-        
-template <typename BitEnumType, typename BitMaskType> 
-void InputHandler<BitEnumType, BitMaskType>::readValue (BitMaskType &mask, TimeMS &dt) {
-    // copy to args
-    mask = this->value;
-    dt = this->dt;
-
-    this->value = 0;
-    this->dt = 0;
-}
-
-template <typename BitEnumType, typename BitMaskType> 
-void InputHandler<BitEnumType, BitMaskType>::update (TimeMS dt) {
-    // all bits that are held down, even those ignored
-    BitMaskType raw_value = 0;
-
-    // update the key-repeat queue
-    queue.update(dt);
-
-    // then go through the keymap
-    for (InputKeymapEntry<BitEnumType> *e = keymap; e->input != 0; e++) {
-        // check if we've got the correct keycodes
-        if (checkKeycode(e->keycodes[0]) && checkKeycode(e->keycodes[1])) {
-            // set raw_value
-            raw_value |= e->input;
-
-            if (e->flags & INPUT_FLAG_SLOWREPEAT) {
-                // repeat, but slowly
-                if (!(prev_value & e->input)) {
-                    // we've released the key earlier, move it to the back of the queue
-                    queue.forget(e->input);
-                    queue.push(e->input);
-
-                } else if (queue.find(e->input)) {
-                    // it's still in the queue, so ignore, but set it in ignore_value
-                    continue;
-
-                } else {
-                    // ok, but add it to the queue
-                    queue.push(e->input);
-                }
-
-            } else if (e->flags & INPUT_FLAG_NOREPEAT) {
-                // do not repeat at all
-                if (prev_value & e->input) {
-                    // ignore repeats
-                    continue;
-                }
-            }
-
-            // set bit in masks
-            this->value |= e->input;
-        }
-    }
-
-    // update prev_value, also adding ignored values
-    prev_value = raw_value;
-
-    // then increment our dt
-    this->dt += dt;
-}
-
-/**
- * Input
- */
-Input::Input (CL_InputDevice &keyboard) :
-    keyboard(keyboard),
-    update_timer(INPUT_POLL_INTERVAL),
-    player(keyboard, INPUT_PLAYER_KEYMAP, INPUT_REPEAT_DELAY),
-    gui(keyboard, INPUT_GUI_KEYMAP, INPUT_REPEAT_DELAY)
-{
-    // connect timer 
-    slots.connect(update_timer.sig_tick(), &player, &InputHandler<PlayerInputBit, PlayerInput>::update);
-    slots.connect(update_timer.sig_tick(), &gui, &InputHandler<GuiInputBit, GuiInput>::update);
-
-    // enable timer
-    update_timer.start();
-}
-
-void Input::readPlayerInput (PlayerInput &mask, TimeMS &dt) {
-    player.readValue(mask, dt);
-}
-
-GuiInput Input::readGuiInput (void) {
-    GuiInput mask;
-    TimeMS dt;
-
-    gui.readValue(mask, dt);
-
-    return mask;
-}
-
--- a/src/Input.hh	Wed Jan 21 23:25:29 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,301 +0,0 @@
-#ifndef INPUT_HH
-#define INPUT_HH
-
-#include "Timer.hh"
-#include "Types.hh"
-
-#include <ClanLib/Display/input_device.h>
-#include <ClanLib/Display/keys.h>
-#include <queue>
-
-// const TimeMS INPUT_INTERVAL_MS = 20;
-
-/**
- * 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 PlayerInput bitmask, each represents a separate action handled by LocalPlayer::handleInput.
- *
- * @see LocalPlayer::handleInput
- */
-enum PlayerInputBit {
-    INPUT_NONE          = 0x0000,
-
-    INPUT_AIM_UP        = 0x0001,
-    INPUT_AIM_DOWN      = 0x0002,
-
-    INPUT_MOVE_LEFT     = 0x0004,
-    INPUT_MOVE_RIGHT    = 0x0008,
-
-    INPUT_JUMP          = 0x0010,
-    INPUT_DIG           = 0x0020,
-    INPUT_SHOOT         = 0x0040,
-    INPUT_CHANGE_NEXT   = 0x0080,
-    INPUT_CHANGE_PREV   = 0x0100,
-    INPUT_ROPE          = 0x0200,
-    INPUT_UNROPE        = 0x0400,
-    INPUT_ROPE_UP       = 0x0800,
-    INPUT_ROPE_DOWN     = 0x1000,
-
-    INPUT_SUICIDE       = 0x2000,
-};
-
-/**
- * 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 of PlayerInputBits
- *
- * @see PlayerInputBit
- */
-typedef uint16_t PlayerInput;
-
-/**
- * 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);
-};
-
-/**
- * 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;
-    
-    public:
-        /**
-         * Constructs the InputHandler using the given keyboard, keymap and key-repeat expire time
-         */
-        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
-         *
-         * @param mask our BitMaskType value is returned using this
-         * @param dt how long the input was held for
-         */
-        void readValue (BitMaskType &mask, TimeMS &dt);
-
-};
-
-/**
- * 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;
-        
-        /**
-         * 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);
-};
-
-#endif
--- a/src/Player.hh	Wed Jan 21 23:25:29 2009 +0200
+++ b/src/Player.hh	Thu Jan 22 00:02:53 2009 +0200
@@ -9,9 +9,9 @@
 #include "Projectile.hh"
 #include "GameState.hh"
 #include "PhysicsObject.hh"
-#include "Input.hh"
 #include "Rope.hh"
 #include "Types.hh"
+#include "Input.hh"
 
 #include "Graphics/Drawable.hh"