Simulant  21.12-574
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
input_state.h
1 /* * Copyright (c) 2011-2017 Luke Benstead https://simulant-engine.appspot.com
2  *
3  * This file is part of Simulant.
4  *
5  * Simulant is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Simulant 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 Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with Simulant. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef INPUT_CONTROLLER_H
20 #define INPUT_CONTROLLER_H
21 
22 #include <cstdint>
23 #include <vector>
24 #include <map>
25 #include <functional>
26 #include <set>
27 #include <cassert>
28 
29 #include "../keycodes.h"
30 #include "../types.h"
31 
32 #include "../signals/signal.h"
33 #include "../generic/managed.h"
34 #include "../generic/identifiable.h"
35 #include "../generic/unique_id.h"
36 
37 namespace smlt {
38 
39 class InputState;
40 
41 typedef int8_t KeyboardID;
42 typedef int8_t MouseID;
43 
44 #define STRONG_TYPEDEF(name, type) \
45  typedef struct tag_ ## name { \
46  type v; \
47  type to_ ## type () const { return v; } \
48  tag_ ## name () {} \
49  explicit tag_ ## name (type i): v(i) {} \
50  bool operator==(const tag_ ## name & rhs) const { return v == rhs.v; } \
51  } (name)
52 
53 
56 STRONG_TYPEDEF(GameControllerID, int8_t);
57 
60 STRONG_TYPEDEF(GameControllerIndex, int8_t);
61 
62 typedef int8_t MouseButtonID;
63 typedef int8_t JoystickHatID;
64 
65 static const KeyboardID ALL_KEYBOARDS = -1;
66 static const MouseID ALL_MICE = -1;
67 static const GameControllerIndex ALL_GAME_CONTROLLERS = GameControllerIndex(-1);
68 
69 
71  GameControllerID id;
72  char name[32];
73  uint8_t button_count;
74  uint8_t axis_count;
75  uint8_t hat_count;
76  bool has_rumble;
77 
78  /* Space for each platform to store some limited data */
79  union {
80  uint32_t i;
81  uint8_t b[4];
82  } platform_data;
83 };
84 
86  uint32_t id;
87 };
88 
90  uint32_t id;
91  uint8_t button_count;
92  uint8_t axis_count;
93 };
94 
95 
96 enum MouseAxis {
97  MOUSE_AXIS_INVALID = -1,
98  MOUSE_AXIS_0,
99  MOUSE_AXIS_1,
100  MOUSE_AXIS_2,
101  MOUSE_AXIS_3,
102  MOUSE_AXIS_MAX,
103  MOUSE_AXIS_X = MOUSE_AXIS_0,
104  MOUSE_AXIS_Y = MOUSE_AXIS_1
105 };
106 
107 enum JoystickAxis {
108  JOYSTICK_AXIS_INVALID = -1,
109  JOYSTICK_AXIS_0,
110  JOYSTICK_AXIS_1,
111  JOYSTICK_AXIS_2,
112  JOYSTICK_AXIS_3,
113  JOYSTICK_AXIS_4,
114  JOYSTICK_AXIS_5,
115  JOYSTICK_AXIS_6,
116  JOYSTICK_AXIS_7,
117  JOYSTICK_AXIS_MAX,
118  JOYSTICK_AXIS_X = JOYSTICK_AXIS_0,
119  JOYSTICK_AXIS_Y = JOYSTICK_AXIS_1,
120  JOYSTICK_AXIS_XL = JOYSTICK_AXIS_0,
121  JOYSTICK_AXIS_YL = JOYSTICK_AXIS_1,
122  JOYSTICK_AXIS_XR = JOYSTICK_AXIS_2,
123  JOYSTICK_AXIS_YR = JOYSTICK_AXIS_3,
124  JOYSTICK_AXIS_LTRIGGER = JOYSTICK_AXIS_4,
125  JOYSTICK_AXIS_RTRIGGER = JOYSTICK_AXIS_5,
126 };
127 
128 enum JoystickHatAxis {
129  JOYSTICK_HAT_AXIS_X,
130  JOYSTICK_HAT_AXIS_Y
131 };
132 
133 /* All IDs here (aside INVALID) match up with those
134  * that SDL uses. This is for convenience */
135 enum JoystickButton : int8_t {
136  JOYSTICK_BUTTON_INVALID = -1,
137  JOYSTICK_BUTTON_A,
138  JOYSTICK_BUTTON_B,
139  JOYSTICK_BUTTON_X,
140  JOYSTICK_BUTTON_Y,
141  JOYSTICK_BUTTON_BACK,
142  JOYSTICK_BUTTON_GUIDE,
143  JOYSTICK_BUTTON_START,
144  JOYSTICK_BUTTON_LEFT_STICK,
145  JOYSTICK_BUTTON_RIGHT_STICK,
146  JOYSTICK_BUTTON_LEFT_SHOULDER,
147  JOYSTICK_BUTTON_RIGHT_SHOULDER,
148  JOYSTICK_BUTTON_DPAD_UP,
149  JOYSTICK_BUTTON_DPAD_DOWN,
150  JOYSTICK_BUTTON_DPAD_LEFT,
151  JOYSTICK_BUTTON_DPAD_RIGHT,
152  JOYSTICK_BUTTON_DPAD2_UP,
153  JOYSTICK_BUTTON_DPAD2_DOWN,
154  JOYSTICK_BUTTON_DPAD2_LEFT,
155  JOYSTICK_BUTTON_DPAD2_RIGHT,
156  JOYSTICK_BUTTON_MAX
157 };
158 
159 const static std::size_t MAX_MOUSE_BUTTONS = 16u;
160 const static std::size_t MAX_JOYSTICK_HATS = 4u;
161 const static std::size_t MAX_DEVICE_TYPE_COUNT = 4u;
162 
163 enum HatPosition {
164  HAT_POSITION_CENTERED = 0,
165  HAT_POSITION_UP = 1,
166  HAT_POSITION_RIGHT = 2,
167  HAT_POSITION_DOWN = 4,
168  HAT_POSITION_LEFT = 8,
169  HAT_POSITION_RIGHT_UP = HAT_POSITION_RIGHT | HAT_POSITION_UP,
170  HAT_POSITION_RIGHT_DOWN = HAT_POSITION_RIGHT | HAT_POSITION_DOWN,
171  HAT_POSITION_LEFT_UP = HAT_POSITION_LEFT | HAT_POSITION_UP,
172  HAT_POSITION_LEFT_DOWN = HAT_POSITION_LEFT | HAT_POSITION_DOWN
173 };
174 
175 class InputState;
176 
178  friend class InputState;
179 
180  GameController() = default;
181  GameController(InputState* parent, GameControllerID id):
182  parent_(parent),
183  id_(id) {}
184 
185 public:
186  GameControllerID id() const {
187  return id_;
188  }
189 
190  GameControllerIndex index() const;
191 
192  bool has_rumble_effect() const;
193 
201  bool start_rumble(float low_rumble, float high_rumble, const smlt::Seconds& duration);
202  void stop_rumble();
203 
204  bool button_state(JoystickButton button) const;
205  float axis_state(JoystickAxis axis) const;
206  HatPosition hat_state(JoystickHatID hat) const;
207 
208  const uint8_t* platform_data() const { return &platform_data_.b[0]; }
209 private:
210  InputState* parent_ = nullptr;
211  GameControllerID id_ = GameControllerID(-1);
212 
213  uint8_t button_count = 0;
214  uint8_t axis_count = 0;
215  uint8_t hat_count = 0;
216 
217  bool has_rumble_ = false;
218  union {
219  uint32_t i;
220  uint8_t b[4];
221  } platform_data_;
222 
223  bool buttons[JOYSTICK_BUTTON_MAX] = {0};
224  float axises[JOYSTICK_AXIS_MAX] = {0};
225  HatPosition hats[MAX_JOYSTICK_HATS] = {HAT_POSITION_CENTERED};
226 };
227 
228 
230  public RefCounted<InputState> {
231 
232 public:
233  InputState(Window* window):
234  window_(window) {}
235 
236  void pre_update(float dt);
237  void update(float dt);
238 
239  /* These methods should be called by BaseWindow subclasses when the OS sends the corresponding
240  * event. You should not call these unless you are implementing support for a new platform!
241  */
242 
243  void _update_mouse_devices(const std::vector<MouseDeviceInfo>& device_info) {
244  mouse_count_ = std::min(device_info.size(), MAX_DEVICE_TYPE_COUNT);
245  for(decltype(mouse_count_) i = 0; i < mouse_count_; ++i) {
246  mice_[i].button_count = device_info[i].button_count;
247  mice_[i].axis_count = device_info[i].axis_count;
248  }
249  }
250 
251  void _update_keyboard_devices(const std::vector<KeyboardDeviceInfo>& device_info) {
252  keyboard_count_ = std::min(device_info.size(), MAX_DEVICE_TYPE_COUNT);
253  }
254 
255  void _update_game_controllers(const std::vector<GameControllerInfo>& device_info);
256 
257  void _handle_key_down(KeyboardID keyboard_id, KeyboardCode code);
258  void _handle_key_up(KeyboardID keyboard_id, KeyboardCode code);
259 
260  void _handle_mouse_motion(MouseID mouse_id, uint32_t x, uint32_t y, int32_t xrel, int32_t yrel);
261  void _handle_mouse_down(MouseID mouse_id, MouseButtonID button_id);
262  void _handle_mouse_up(MouseID mouse_id, MouseButtonID button_id);
263 
264  // value must be a value between -1.0f and 1.0f!
265  void _handle_joystick_axis_motion(GameControllerID joypad_id, JoystickAxis axis, float value);
266 
267  void _handle_joystick_button_down(GameControllerID joypad_id, JoystickButton button);
268  void _handle_joystick_button_up(GameControllerID joypad_id, JoystickButton button);
269  void _handle_joystick_hat_motion(GameControllerID joypad_id, JoystickHatID hat_id, HatPosition position);
270 
271  // Public state accessor functions
272  bool keyboard_key_state(KeyboardID keyboard_id, KeyboardCode code) const;
273 
274  bool mouse_button_state(MouseID mouse_id, MouseButtonID button) const;
275 
276  float mouse_axis_state(MouseID mouse_id, MouseAxis axis) const;
277  Vec2 mouse_position(MouseID mouse_id) const;
278 
279  GameController* game_controller_by_id(GameControllerID id);
280  const GameController* game_controller_by_id(GameControllerID id) const;
281  GameController* game_controller(GameControllerIndex id);
282  GameControllerIndex game_controller_index_from_id(GameControllerID id) const;
283 
284  std::size_t game_controller_count() const { return joystick_count_; }
285  std::size_t keyboard_count() const { return keyboard_count_; }
286  std::size_t mouse_count() const { return mouse_count_; }
287 
288  JoystickAxis linked_axis(GameControllerID id, JoystickAxis axis);
289 
290 private:
291  friend class GameController;
292 
293  Window* window_ = nullptr;
294 
295  bool joystick_button_state(GameControllerID joystick_id, JoystickButton button) const;
296  float joystick_axis_state(GameControllerID joystick_id, JoystickAxis axis) const;
297  HatPosition joystick_hat_state(GameControllerID joystick_id, JoystickHatID hat) const;
298 
299 
300  struct KeyboardState {
301  bool keys[MAX_KEYBOARD_CODES] = {0};
302  };
303 
304  uint8_t keyboard_count_ = 0;
305  KeyboardState keyboards_[4];
306 
307  struct MouseState {
308  uint8_t button_count = 0;
309  uint8_t axis_count = 0;
310 
311  bool buttons[MAX_MOUSE_BUTTONS] = {0};
312  float axises[MOUSE_AXIS_MAX] = {0};
313 
314  uint32_t x = 0;
315  uint32_t y = 0;
316  };
317 
318  uint8_t mouse_count_ = 0;
319  MouseState mice_[4];
320 
321  uint8_t joystick_count_ = 0;
322  GameController joysticks_[4];
323 };
324 
325 }
326 #endif // INPUT_CONTROLLER_H
smlt::KeyboardDeviceInfo
Definition: input_state.h:85
smlt::GameControllerInfo
Definition: input_state.h:70
smlt::STRONG_TYPEDEF
STRONG_TYPEDEF(GameControllerID, int8_t)
smlt::RefCounted
Definition: managed.h:65
smlt
Definition: animation.cpp:25
smlt::GameController::start_rumble
bool start_rumble(float low_rumble, float high_rumble, const smlt::Seconds &duration)
Start a rumble effect on the controller.
Definition: input_state.cpp:249
smlt::Window
Definition: window.h:65
smlt::MouseDeviceInfo
Definition: input_state.h:89
smlt::Seconds
Definition: types.h:55
smlt::InputState
Definition: input_state.h:230
smlt::GameController
Definition: input_state.h:177
smlt::Vec2
Definition: vec2.h:14