Simulant  21.12-1292
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 "../core/stage_node_id.h"
36 #include "../utils/limited_vector.h"
37 namespace smlt {
38 
39 class InputState;
40 
41 #define STRONG_TYPEDEF(name, type) \
42  typedef struct tag_##name { \
43  type to_##type() const { \
44  return v; \
45  } \
46  tag_##name() {} \
47  explicit tag_##name(type i) : \
48  v(i) {} \
49  bool operator==(const tag_##name& rhs) const { \
50  return v == rhs.v; \
51  } \
52  bool operator<(const tag_##name& rhs) const { \
53  return v < rhs.v; \
54  } \
55  \
56  private: \
57  type v; \
58  } name
59 
60 STRONG_TYPEDEF(MouseID, int8_t);
61 STRONG_TYPEDEF(KeyboardID, int8_t);
62 
65 STRONG_TYPEDEF(GameControllerID, int8_t);
66 
69 STRONG_TYPEDEF(GameControllerIndex, int8_t);
70 
71 typedef int8_t MouseButtonID;
72 typedef int8_t JoystickHatID;
73 
74 static const KeyboardID ALL_KEYBOARDS = KeyboardID(-1);
75 static const MouseID ALL_MICE = MouseID(-1);
76 static const GameControllerIndex ALL_GAME_CONTROLLERS = GameControllerIndex(-1);
77 
78 
80  GameControllerID id;
81  char name[32];
82  uint8_t button_count;
83  uint8_t axis_count;
84  uint8_t hat_count;
85  bool has_rumble;
86 
87  /* Space for each platform to store some limited data */
88  union {
89  uint32_t i;
90  uint8_t b[4];
91  } platform_data;
92 };
93 
94 enum KeyboardType {
95  KEYBOARD_TYPE_PHYSICAL,
96  KEYBOARD_TYPE_SOFTWARE,
97 };
98 
100  uint32_t id;
101  KeyboardType type = KEYBOARD_TYPE_PHYSICAL;
102 };
103 
105  uint32_t id;
106  uint8_t button_count;
107  uint8_t axis_count;
108 };
109 
110 
111 enum MouseAxis {
112  MOUSE_AXIS_INVALID = -1,
113  MOUSE_AXIS_0,
114  MOUSE_AXIS_1,
115  MOUSE_AXIS_2,
116  MOUSE_AXIS_3,
117  MOUSE_AXIS_MAX,
118  MOUSE_AXIS_X = MOUSE_AXIS_0,
119  MOUSE_AXIS_Y = MOUSE_AXIS_1
120 };
121 
122 enum JoystickAxis {
123  JOYSTICK_AXIS_INVALID = -1,
124  JOYSTICK_AXIS_0,
125  JOYSTICK_AXIS_1,
126  JOYSTICK_AXIS_2,
127  JOYSTICK_AXIS_3,
128  JOYSTICK_AXIS_4,
129  JOYSTICK_AXIS_5,
130  JOYSTICK_AXIS_6,
131  JOYSTICK_AXIS_7,
132  JOYSTICK_AXIS_MAX,
133  JOYSTICK_AXIS_X = JOYSTICK_AXIS_0,
134  JOYSTICK_AXIS_Y = JOYSTICK_AXIS_1,
135  JOYSTICK_AXIS_XL = JOYSTICK_AXIS_0,
136  JOYSTICK_AXIS_YL = JOYSTICK_AXIS_1,
137  JOYSTICK_AXIS_XR = JOYSTICK_AXIS_2,
138  JOYSTICK_AXIS_YR = JOYSTICK_AXIS_3,
139  JOYSTICK_AXIS_LTRIGGER = JOYSTICK_AXIS_4,
140  JOYSTICK_AXIS_RTRIGGER = JOYSTICK_AXIS_5,
141 };
142 
143 enum JoystickHatAxis {
144  JOYSTICK_HAT_AXIS_X,
145  JOYSTICK_HAT_AXIS_Y
146 };
147 
148 /* All IDs here (aside INVALID) match up with those
149  * that SDL uses. This is for convenience */
150 enum JoystickButton : int8_t {
151  JOYSTICK_BUTTON_INVALID = -1,
152  JOYSTICK_BUTTON_A,
153  JOYSTICK_BUTTON_B,
154  JOYSTICK_BUTTON_X,
155  JOYSTICK_BUTTON_Y,
156  JOYSTICK_BUTTON_BACK,
157  JOYSTICK_BUTTON_GUIDE,
158  JOYSTICK_BUTTON_START,
159  JOYSTICK_BUTTON_LEFT_STICK,
160  JOYSTICK_BUTTON_RIGHT_STICK,
161  JOYSTICK_BUTTON_LEFT_SHOULDER,
162  JOYSTICK_BUTTON_RIGHT_SHOULDER,
163  JOYSTICK_BUTTON_DPAD_UP,
164  JOYSTICK_BUTTON_DPAD_DOWN,
165  JOYSTICK_BUTTON_DPAD_LEFT,
166  JOYSTICK_BUTTON_DPAD_RIGHT,
167  JOYSTICK_BUTTON_DPAD2_UP,
168  JOYSTICK_BUTTON_DPAD2_DOWN,
169  JOYSTICK_BUTTON_DPAD2_LEFT,
170  JOYSTICK_BUTTON_DPAD2_RIGHT,
171  JOYSTICK_BUTTON_MAX
172 };
173 
174 const static std::size_t MAX_MOUSE_BUTTONS = 16u;
175 const static std::size_t MAX_JOYSTICK_HATS = 4u;
176 const static std::size_t MAX_DEVICE_TYPE_COUNT = 4u;
177 
178 enum HatPosition {
179  HAT_POSITION_CENTERED = 0,
180  HAT_POSITION_UP = 1,
181  HAT_POSITION_RIGHT = 2,
182  HAT_POSITION_DOWN = 4,
183  HAT_POSITION_LEFT = 8,
184  HAT_POSITION_RIGHT_UP = HAT_POSITION_RIGHT | HAT_POSITION_UP,
185  HAT_POSITION_RIGHT_DOWN = HAT_POSITION_RIGHT | HAT_POSITION_DOWN,
186  HAT_POSITION_LEFT_UP = HAT_POSITION_LEFT | HAT_POSITION_UP,
187  HAT_POSITION_LEFT_DOWN = HAT_POSITION_LEFT | HAT_POSITION_DOWN
188 };
189 
190 class InputState;
191 
193  friend class InputState;
194 
195  GameController(InputState* parent, GameControllerID id) :
196  parent_(parent), id_(id) {}
197 
198 public:
199  GameController() = default;
200 
201  GameControllerID id() const {
202  return id_;
203  }
204 
205  GameControllerIndex index() const;
206 
207  bool has_rumble_effect() const;
208 
216  bool start_rumble(float low_rumble, float high_rumble, const smlt::Seconds& duration);
217  void stop_rumble();
218 
219  bool button_state(JoystickButton button) const;
220  float axis_state(JoystickAxis axis) const;
221  HatPosition hat_state(JoystickHatID hat) const;
222 
223  const uint8_t* platform_data() const { return &platform_data_.b[0]; }
224 private:
225  InputState* parent_ = nullptr;
226  GameControllerID id_ = GameControllerID(-1);
227 
228  uint8_t button_count = 0;
229  uint8_t axis_count = 0;
230  uint8_t hat_count = 0;
231 
232  bool has_rumble_ = false;
233  union {
234  uint32_t i;
235  uint8_t b[4];
236  } platform_data_;
237 
238  bool buttons[JOYSTICK_BUTTON_MAX] = {0};
239  float axises[JOYSTICK_AXIS_MAX] = {0};
240  HatPosition hats[MAX_JOYSTICK_HATS] = {HAT_POSITION_CENTERED};
241 };
242 
243 
244 struct Keyboard {
245  bool keys[MAX_KEYBOARD_CODES] = {0};
246  KeyboardType type;
247 };
248 
250  public RefCounted<InputState> {
251 
252 public:
253  InputState(Window* window):
254  window_(window) {}
255 
256  void pre_update(float dt);
257  void update(float dt);
258 
259  /* These methods should be called by BaseWindow subclasses when the OS sends the corresponding
260  * event. You should not call these unless you are implementing support for a new platform!
261  */
262 
263  void _update_mouse_devices(const std::vector<MouseDeviceInfo>& device_info) {
264  mice_.clear();
265  for(std::size_t i = 0; i < device_info.size(); ++i) {
266  auto mouse = MouseState();
267  mouse.button_count = device_info[i].button_count;
268  mouse.axis_count = device_info[i].axis_count;
269  mice_.push_back(mouse);
270  }
271  }
272 
273  void _update_keyboard_devices(const std::vector<KeyboardDeviceInfo>& device_info) {
274  keyboards_.clear();
275  for(std::size_t i = 0; i < device_info.size(); ++i) {
276  auto keyboard = Keyboard();
277  keyboard.type = device_info[i].type;
278  keyboards_.push_back(keyboard);
279  }
280  }
281 
282  void _update_game_controllers(const std::vector<GameControllerInfo>& device_info);
283 
284  void _handle_key_down(KeyboardID keyboard_id, KeyboardCode code);
285  void _handle_key_up(KeyboardID keyboard_id, KeyboardCode code);
286 
287  void _handle_mouse_motion(MouseID mouse_id, uint32_t x, uint32_t y, int32_t xrel, int32_t yrel);
288  void _handle_mouse_down(MouseID mouse_id, MouseButtonID button_id);
289  void _handle_mouse_up(MouseID mouse_id, MouseButtonID button_id);
290 
291  // value must be a value between -1.0f and 1.0f!
292  void _handle_joystick_axis_motion(GameControllerID joypad_id, JoystickAxis axis, float value);
293 
294  void _handle_joystick_button_down(GameControllerID joypad_id, JoystickButton button);
295  void _handle_joystick_button_up(GameControllerID joypad_id, JoystickButton button);
296  void _handle_joystick_hat_motion(GameControllerID joypad_id, JoystickHatID hat_id, HatPosition position);
297 
298  // Public state accessor functions
299  bool keyboard_key_state(KeyboardID keyboard_id, KeyboardCode code) const;
300 
301  bool mouse_button_state(MouseID mouse_id, MouseButtonID button) const;
302 
303  float mouse_axis_state(MouseID mouse_id, MouseAxis axis) const;
304  Vec2 mouse_position(MouseID mouse_id) const;
305 
306  GameController* game_controller_by_id(GameControllerID id);
307  const GameController* game_controller_by_id(GameControllerID id) const;
308  GameController* game_controller(GameControllerIndex id);
309  GameControllerIndex game_controller_index_from_id(GameControllerID id) const;
310 
311  std::size_t game_controller_count() const {
312  return game_controllers_.size();
313  }
314  std::size_t keyboard_count() const {
315  return keyboards_.size();
316  }
317 
318  Keyboard* keyboard_by_id(KeyboardID keyboard_id);
319  const Keyboard* keyboard_by_id(KeyboardID keyboard_id) const;
320 
321  std::size_t mouse_count() const {
322  return mice_.size();
323  }
324 
325  JoystickAxis linked_axis(GameControllerID id, JoystickAxis axis);
326 
327 private:
328  friend class GameController;
329 
330  Window* window_ = nullptr;
331 
332  bool joystick_button_state(GameControllerID joystick_id, JoystickButton button) const;
333  float joystick_axis_state(GameControllerID joystick_id, JoystickAxis axis) const;
334  HatPosition joystick_hat_state(GameControllerID joystick_id, JoystickHatID hat) const;
335 
336  struct MouseState {
337  uint8_t button_count = 0;
338  uint8_t axis_count = 0;
339 
340  bool buttons[MAX_MOUSE_BUTTONS] = {0};
341  float axises[MOUSE_AXIS_MAX] = {0};
342 
343  uint32_t x = 0;
344  uint32_t y = 0;
345  };
346 
347  LimitedVector<Keyboard, 4> keyboards_;
349  LimitedVector<GameController, 4> game_controllers_;
350 };
351 
352 }
353 #endif // INPUT_CONTROLLER_H
smlt::KeyboardDeviceInfo
Definition: input_state.h:99
smlt::GameControllerInfo
Definition: input_state.h:79
smlt::RefCounted
Definition: managed.h:71
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:267
smlt::Window
Definition: window.h:68
smlt::LimitedVector
Definition: limited_vector.h:13
smlt::MouseDeviceInfo
Definition: input_state.h:104
smlt::Keyboard
Definition: input_state.h:244
smlt::Seconds
Definition: types.h:55
smlt::InputState
Definition: input_state.h:250
smlt::GameController
Definition: input_state.h:192
smlt::Vec2
Definition: vec2.h:16