1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2010-2015 SuperTuxKart-Team
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #ifndef DEVICE_MANAGER_HPP
20 #define DEVICE_MANAGER_HPP
21 
22 #include "input/gamepad_config.hpp"
23 #include "input/input_manager.hpp"
24 #include "input/keyboard_config.hpp"
25 #include "states_screens/state_manager.hpp"
26 #include "utils/no_copy.hpp"
27 #include "utils/ptr_vector.hpp"
28 
29 #include <irrArray.h>
30 #include <IEventReceiver.h>
31 using namespace irr;
32 
33 class DeviceConfig;
34 class InputDevice;
35 class GamePadDevice;
36 class KeyboardDevice;
37 class MultitouchDevice;
38 
39 
40 enum PlayerAssignMode
41 {
42     NO_ASSIGN,  //!< react to all devices
43     DETECT_NEW, //!< notify the manager when an inactive device is being asked to activate with fire
44     ASSIGN      //!< only react to assigned devices
45 };
46 
47 /**
48  * \brief This class holds the list of all known devices (ands their configurations), as well as the
49  * list of currently plugged (used) devices.
50  * It thus takes care of finding to which device any given
51  * input belongs, and what action each keypress is bound to, if any (and, since each device is
52  * associated to a player, it also finds which player triggered this action)
53  * These input mapping capabilities should *only* be used through the InputManager, not directly.
54  *
55  * The device manager starts in "no-assign" mode, which means no input configuration is associated
56  * to any player. So all devices will react. This is used in menus before player set-up is done.
57  * Switching back to no-assign mode will also clear anything in devices that was associated with
58  * players in assign mode.
59  *
60  * \ingroup input
61  */
62 class DeviceManager: public NoCopy
63 {
64 private:
65 
66     PtrVector<KeyboardDevice, HOLD>    m_keyboards;
67     PtrVector<GamePadDevice, HOLD>     m_gamepads;
68     PtrVector<KeyboardConfig, HOLD>    m_keyboard_configs;
69     PtrVector<GamepadConfig, HOLD>     m_gamepad_configs;
70     MultitouchDevice*                  m_multitouch_device;
71 
72     InputDevice*                       m_latest_used_device;
73     PlayerAssignMode                   m_assign_mode;
74 
75 
76     /** Will be non-null in single-player mode */
77     StateManager::ActivePlayer* m_single_player;
78 
79     /** If this is flag is set the next fire event (if the fire key is not
80      *  mapped to anything else) will be mapped to 'select'. This is used
81      *  in the kart select GUI to support the old way of adding players by
82      *  pressing fire. */
83     bool m_map_fire_to_select;
84 
85 
86     InputDevice *mapGamepadInput( Input::InputType type, int deviceID,
87                                   int btnID, int axisDir,
88                                   int* value /* inout */,
89                                   InputManager::InputDriverMode mode,
90                                   StateManager::ActivePlayer **player /* out */,
91                                   PlayerAction *action /* out */);
92     InputDevice *mapKeyboardInput(int button_id,
93                                   InputManager::InputDriverMode mode,
94                                   StateManager::ActivePlayer **player /* out */,
95                                   PlayerAction *action /* out */);
96 
97     bool load();
98     void shutdown();
99 
100 public:
101 
102 
103     DeviceManager();
104     ~DeviceManager();
105 
106     // ---- Assign mode ----
getAssignMode() const107     PlayerAssignMode    getAssignMode() const               { return m_assign_mode; }
108     void                setAssignMode(const PlayerAssignMode assignMode);
109 
110     // ---- Gamepads ----
111     void addGamepad(GamePadDevice* d);
getGamePadAmount() const112     int getGamePadAmount() const                            { return m_gamepads.size(); }
getGamePadConfigAmount() const113     int getGamePadConfigAmount() const                      { return m_gamepad_configs.size(); }
getGamePad(const int i)114     GamePadDevice*      getGamePad(const int i)             { return m_gamepads.get(i); }
getGamepadConfig(const int i)115     GamepadConfig*      getGamepadConfig(const int i)       { return m_gamepad_configs.get(i); }
116     GamePadDevice*      getGamePadFromIrrID(const int i);
117     void                clearGamepads();
118     /** Returns the keyboard that has a binding for this button, or NULL if none */
119     bool                getConfigForGamepad(const int sdl_id,
120                                             const std::string& name,
121                                             GamepadConfig **config);
122 
123     // ---- Keyboard(s) ----
124     void addEmptyKeyboard();
125     void addKeyboard(KeyboardDevice* d);
126     void                clearKeyboard();
getKeyboardAmount()127     int                 getKeyboardAmount()                 { return m_keyboards.size(); }
getActiveKeyboardAmount()128     int                 getActiveKeyboardAmount()
129     {
130         int active = 0;
131         for (unsigned int i=0;i<m_keyboard_configs.size();i++)
132         {
133             if (m_keyboard_configs[i].isEnabled()) active++;
134         }
135         return active;
136     }
getKeyboardConfigAmount() const137     int                 getKeyboardConfigAmount() const     { return m_keyboard_configs.size(); }
getKeyboard(const int i)138     KeyboardDevice*     getKeyboard(const int i)            { return m_keyboards.get(i); }
getKeyboardConfig(const int i)139     KeyboardConfig*     getKeyboardConfig(const int i)      { return m_keyboard_configs.get(i); }
140     KeyboardDevice*     getKeyboardFromBtnID(const int btnID);
141 
142     // ---- Multitouch device ----
getMultitouchDevice()143     MultitouchDevice*   getMultitouchDevice()    { return m_multitouch_device; }
144     void                clearMultitouchDevices();
145     void                updateMultitouchDevice();
146 
147 
148     /**
149       * \brief Delete the given config and removes DeviceManager references to it.
150       */
151     bool deleteConfig(DeviceConfig* config);
152 
153     /** Given some input, finds to which device it belongs and, using the corresponding device object,
154       * maps this input to the corresponding player and game action.
155       *
156       * \return false if player/action could not be set.
157       * \note   Special case : can return 'true' but set action to PA_BEFORE_FIRST if the input was used but
158       *         is not associated to an action and a player
159       *
160       * \param mode used to determine whether to map game actions or menu actions
161       */
162     bool translateInput( Input::InputType type,
163                          int deviceID,
164                          int btnID,
165                          int axisDir,
166                          int *value /* inout */,
167                          InputManager::InputDriverMode mode,
168                          StateManager::ActivePlayer** player /* out */,
169                          PlayerAction* action /* out */ );
170 
171     void                clearLatestUsedDevice();
172     InputDevice*        getLatestUsedDevice();
173     bool initialize();
174     void save();
175 
176     // ------------------------------------------------------------------------
177     /** Returns the active player if there is only a single local player. It
178      *  returns NULL if multiplayer is active. */
getSinglePlayer()179     StateManager::ActivePlayer* getSinglePlayer()  { return m_single_player; }
180     // ------------------------------------------------------------------------
181     /** Sets the ActivePlayer if there is only a single local player. p must
182      *  be NULL in case of splitscreen. A single player will receive events
183      *  from all connected devices. This allows for example a single player
184      *  to select a kart with the keyboard, but then use a gamepad for
185      *  the actual racing. In splitscreen each player will only receive
186      *  events from the device used to connect in the kart selection screen. */
setSinglePlayer(StateManager::ActivePlayer * p)187     void setSinglePlayer(StateManager::ActivePlayer* p)
188     {
189         m_single_player = p;
190     }   // setSinglePlayer
191     // ------------------------------------------------------------------------
192     /** Sets or reset the 'map fire to select' option.
193      */
mapFireToSelect(bool v)194     void mapFireToSelect(bool v) {m_map_fire_to_select = v; }
195 
196 };   // DeviceManager
197 
198 
199 #endif
200