The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
joystick.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2016 by Fabian Mueller
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "joystick.hpp"
16 #include "preferences.hpp"
17 #include "log.hpp"
18 #include <boost/math/constants/constants.hpp>
19 using namespace boost::math::constants;
20 
21 static lg::log_domain log_joystick("joystick");
22 #define ERR_JOY LOG_STREAM(err, log_joystick)
23 #define LOG_JOY LOG_STREAM(info, log_joystick)
24 #define DBG_JOY LOG_STREAM(debug, log_joystick)
25 
27  : joysticks_()
28  , joystick_area_(0)
29  , counter_(0)
30 {
31  init();
32 }
33 
35  close();
36 }
37 
38 
39 static bool attached(
40  const std::vector<SDL_Joystick*>& joysticks
41  , const size_t index)
42 {
43  return SDL_JoystickGetAttached(joysticks[index]) == SDL_TRUE;
44 }
45 
46 static const char* name(
47  const std::vector<SDL_Joystick*>& joysticks
48  , const size_t index)
49 {
50  return SDL_JoystickName(joysticks[index]);
51 }
52 
53 
55  if(SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
56  return true;
57 
58  int joysticks = joysticks_.size();
59  bool all_closed = true;
60 
61  for (int i = 0; i<joysticks; i++) {
62  if (attached(joysticks_, i)) {
63  SDL_JoystickClose(joysticks_[i]);
64  LOG_JOY << "Closed Joystick" << i;
65  LOG_JOY << "Name: " << name(joysticks_, i);
66  } else {
67  ERR_JOY << "Joystick" << i << " closing failed.";
68  all_closed = false;
69  }
70  }
71 
72  joysticks_.clear();
73  return all_closed;
74 }
75 
77 
78  close();
79 
81  LOG_JOY << "Joystick support is disabled.";
82  return false;
83  }
84 
85  LOG_JOY << "Initializing joysticks...\n";
86  if(SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
87  if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
88  return false;
89 
90  joysticks_.clear();
91 
92  int joysticks = SDL_NumJoysticks();
93  if (joysticks == 0) return false;
94 
95  SDL_JoystickEventState(SDL_ENABLE);
96 
97  bool joystick_found = false;
98  for (int i = 0; i<joysticks; i++) {
99  joysticks_.resize(i+1);
100  joysticks_[i] = SDL_JoystickOpen(i);
101 
102  if (joysticks_[i] && attached(joysticks_, i)) {
103 
104  joystick_found = true;
105 
106  LOG_JOY << "Opened Joystick" << i;
107  LOG_JOY << "Name: " << name(joysticks_, i);
108  LOG_JOY << "Number of Axes: " << SDL_JoystickNumAxes(joysticks_[i]);
109  LOG_JOY << "Number of Buttons: " << SDL_JoystickNumButtons(joysticks_[i]);
110  LOG_JOY << "Number of Balls: " << SDL_JoystickNumBalls(joysticks_[i]);
111  LOG_JOY << "Number of Hats: ", SDL_JoystickNumHats(joysticks_[i]);
112  } else {
113  ERR_JOY << "Couldn't open Joystick" << i;
114  }
115  }
116  return joystick_found;
117 }
118 
119 std::pair<double, double> joystick_manager::get_mouse_axis_pair() {
120 
121  const int mouse_joystick_x = preferences::joystick_num_mouse_xaxis();
122  const int mouse_xaxis = preferences::joystick_mouse_xaxis_num();
123 
124  const int mouse_joystick_y = preferences::joystick_num_mouse_yaxis();
125  const int mouse_yaxis = preferences::joystick_mouse_yaxis_num();
126 
127  std::pair<int, int> values;
128  double thrust;
129  {
130  values = get_axis_pair(mouse_joystick_x, mouse_xaxis, mouse_joystick_y, mouse_yaxis);
131  thrust = get_thrusta_axis();
132  }
133 
134  const int radius = round_double(sqrt(pow(values.first, 2.0f) + pow(values.second, 2.0f)));
135  const int deadzone = preferences::joystick_mouse_deadzone();
136  const double multiplier = 1.0 + thrust;
137 
138  if (deadzone > radius)
139  return std::make_pair(0.0, 0.0);
140 
141  // TODO do some math to normalize over the value - deadzone.
142  //const double relation = abs( (double)values.first / (double)values.second );
143  //const int range_x = values.first - round_double(relation * deadzone);
144  //const int range_y = values.second - ((1.0 - relation) * deadzone);
145  //double x_value = ((double)(values.first - deadzone) / (double)(32768 - deadzone)) *
146 
147  return std::make_pair(
148  ((static_cast<double>(values.first)) / 32768.0) * multiplier
149  , ((static_cast<double>(values.second)) / 32768.0) * multiplier );
150 
151 }
152 
153 std::pair<double, double> joystick_manager::get_scroll_axis_pair() {
154 
155  if (!preferences::joystick_support_enabled()) return std::make_pair(0.0, 0.0);
156 
157  const int scroll_joystick_x = preferences::joystick_num_scroll_xaxis();
158  const int scroll_axis = preferences::joystick_scroll_xaxis_num();
159 
160  const int scroll_joystick_y = preferences::joystick_num_scroll_yaxis();
161  const int scroll_yaxis = preferences::joystick_scroll_yaxis_num();
162 
163  std::pair<int, int> values;
164  double thrust;
165  {
166  values = get_axis_pair(scroll_joystick_x, scroll_axis, scroll_joystick_y, scroll_yaxis);
167  thrust = get_thrusta_axis();
168  }
169 
170  const int radius = round_double(sqrt(pow(values.first, 2.0f) + pow(values.second, 2.0f)));
171  const int deadzone = preferences::joystick_scroll_deadzone();
172  const double multiplier = 1.0 + thrust;
173 
174  if (deadzone > radius)
175  return std::make_pair(0.0, 0.0);
176 
177  return std::make_pair(
178  ((static_cast<double>(values.first)) / 32768.0) * multiplier
179  , ((static_cast<double>(values.second)) / 32768.0) * multiplier );
180 }
181 
183  if (!preferences::joystick_support_enabled()) return 0.0;
184 
185  const int thrust_joystick_x = preferences::joystick_num_thrusta_axis();
186  const int thrust_axis_x = preferences::joystick_thrusta_axis_num();
187  const int thrust_deadzone = preferences::joystick_thrusta_deadzone();
188 
189  const int value = get_axis(thrust_joystick_x, thrust_axis_x) + 32768;
190  if (value < thrust_deadzone) return 0.0;
191  return static_cast<double>(value) / 65536.0;
192 }
193 
195  if (!preferences::joystick_support_enabled()) return 0.0;
196 
197  const int thrustb_joystick = preferences::joystick_num_thrustb_axis();
198  const int thrustb_axis = preferences::joystick_thrustb_axis_num();
199  const int thrustb_deadzone = preferences::joystick_thrustb_deadzone();
200 
201  const int value = get_axis(thrustb_joystick, thrustb_axis) + 32768;
202  if (value < thrustb_deadzone) return 0.0;
203  return static_cast<double>(value) / 65536.0;
204 }
205 
207  const int cursor_joystick_xaxis = preferences::joystick_num_cursor_xaxis();
208  const int cursor_xaxis = preferences::joystick_cursor_xaxis_num();
209 
210  const int cursor_joystick_yaxis = preferences::joystick_num_cursor_yaxis();
211  const int cursor_yaxis = preferences::joystick_cursor_yaxis_num();
212 
213  return get_polar_coordinates(cursor_joystick_xaxis, cursor_xaxis, cursor_joystick_yaxis, cursor_yaxis);
214 }
215 
216 std::pair<double, double> joystick_manager::get_polar_coordinates(int joystick_xaxis, int xaxis, int joystick_yaxis, int yaxis) {
217 
218  const std::pair<int, int> values = get_axis_pair(joystick_xaxis, xaxis, joystick_yaxis, yaxis);
219  const double radius = (sqrt(pow(values.first, 2.0f) + pow(values.second, 2.0f))) / 32768.0;
220  const double angle = (atan2(
221  static_cast<double>(values.second)
222  , static_cast<double>(values.first))) * 180.0 / pi<double>();
223 
224  return std::make_pair(radius, angle);
225 }
226 
227 std::pair<int, int> joystick_manager::get_axis_pair(int joystick_xaxis, int xaxis, int joystick_yaxis, int yaxis) {
228 
229  if(!SDL_WasInit(SDL_INIT_JOYSTICK))
230  return std::make_pair(0, 0);
231 
232  int x_axis = 0, y_axis = 0;
233  bool get_xaxis = false, get_yaxis = false;
234 
235  if(attached(joysticks_, joystick_xaxis))
236  if(SDL_JoystickNumAxes(joysticks_[joystick_xaxis]) > xaxis)
237  get_xaxis = true;
238 
239  if(attached(joysticks_, joystick_yaxis))
240  if(SDL_JoystickNumAxes(joysticks_[joystick_yaxis]) > yaxis)
241  get_yaxis = true;
242 
243  //TODO Does the block prevent the commands from being interrupted?
244  //We want the readings to be from a similar time slice.
245  {
246  if (get_xaxis) x_axis = SDL_JoystickGetAxis(joysticks_[joystick_xaxis], xaxis);
247  if (get_yaxis) y_axis = SDL_JoystickGetAxis(joysticks_[joystick_yaxis], yaxis);
248  }
249  return std::make_pair(x_axis, y_axis);
250 }
251 
252 int joystick_manager::get_axis(int joystick_axis, int axis) {
253  if(!SDL_WasInit(SDL_INIT_JOYSTICK))
254  return 0;
255 
256  if(attached(joysticks_, joystick_axis))
257  if(SDL_JoystickNumAxes(joysticks_[joystick_axis]) > axis)
258  return SDL_JoystickGetAxis(joysticks_[joystick_axis], axis);
259  return 0;
260 }
261 
262 
263 bool joystick_manager::update_highlighted_hex(map_location& highlighted_hex, const map_location& selected_hex) {
264 
265  const int cursor_joystick_xaxis = preferences::joystick_num_cursor_xaxis();
266  const int cursor_xaxis = preferences::joystick_cursor_xaxis_num();
267 
268  const int cursor_joystick_yaxis = preferences::joystick_num_cursor_yaxis();
269  const int cursor_yaxis = preferences::joystick_cursor_yaxis_num();
270 
271  const std::pair<int, int> values = get_axis_pair(cursor_joystick_xaxis, cursor_xaxis, cursor_joystick_yaxis, cursor_yaxis);
272 
273  const int x_axis = values.first;
274  const int y_axis = values.second;
275 
276  //const int radius = round_double(sqrt(pow(x_axis, 2.0f) + pow(y_axis, 2.0f)));
277 
278 // const int deadzone = preferences::joystick_cursor_deadzone();
279  //const int threshold2 = 10*threshold;
280  //const int max = 100000;
281 
282  //const bool greater_deadzone = radius > deadzone;
283  //const bool greater_threshold2 = radius > threshold2;
284 
285  int x = selected_hex.x + round_double(x_axis / 3200);
286  int y = selected_hex.y + round_double(y_axis / 3200);
287  highlighted_hex = map_location(x,y);
288 
289  //if (!greater_threshold) {
290  // counter_ = 0;
291  // joystick_area_ = 0;
292  // return false;
293  //}
294 
295  return true;
296 }
297 
298 
300 
301  const int cursor_joystick_xaxis = preferences::joystick_num_cursor_xaxis();
302  const int cursor_xaxis = preferences::joystick_cursor_xaxis_num();
303 
304  const int cursor_joystick_yaxis = preferences::joystick_num_cursor_yaxis();
305  const int cursor_yaxis = preferences::joystick_cursor_yaxis_num();
306 
307  const std::pair<int, int> values = get_axis_pair(cursor_joystick_xaxis, cursor_xaxis, cursor_joystick_yaxis, cursor_yaxis);
308 
309  const int x_axis = values.first;
310  const int y_axis = values.second;
311 
312  const int radius = round_double(sqrt(pow(x_axis, 2.0f) + pow(y_axis, 2.0f)));
313 
314  const int deadzone = preferences::joystick_cursor_deadzone();
315  const int threshold = deadzone + preferences::joystick_cursor_threshold();
316  //TODO fendrin take max from preferences as well
317  const int max = 100000;
318 
319  const bool greater_deadzone = radius > deadzone;
320  const bool greater_threshold2 = radius > threshold;
321 
322  if (!greater_deadzone) {
323  counter_ = 0;
324  joystick_area_ = 0;
325  return false;
326  } else {
327  if (joystick_area_ == 0) {
328  highlighted_hex = get_next_hex(x_axis, y_axis, highlighted_hex);
329  }
330  if (!greater_threshold2) {
331  joystick_area_ = 1;
332  } else {
333  joystick_area_ = 2;
334  counter_ += radius;
335  if (counter_ > max) {
336  counter_ -= max;
337  highlighted_hex = get_next_hex(x_axis, y_axis, highlighted_hex);
338  return true;
339  } else return false;
340  }
341  }
342 
343  return true;
344 }
345 
347 
348  int x = loc.x;
349  int y = loc.y;
350 
351  switch(direction) {
352  case NORTH: return map_location(x, y - 1);
353  case SOUTH: return map_location(x, y + 1);
354  case SOUTH_EAST: return map_location(x + 1, y + (1+is_odd(x))/2 );
355  case SOUTH_WEST: return map_location(x - 1, y + (1+is_odd(x))/2 );
356  case NORTH_EAST: return map_location(x + 1, y - (1+is_even(x))/2 );
357  case NORTH_WEST: return map_location(x - 1, y - (1+is_even(x))/2 );
358  case WEST: return map_location(x - 1, y);
359  case EAST: return map_location(x + 1, y);
360  default:
361  assert(false);
362  return map_location();
363  }
364 }
365 
367 
368  const int cursor_joystick_xaxis = preferences::joystick_num_cursor_xaxis();
369  const int cursor_xaxis = preferences::joystick_cursor_xaxis_num();
370 
371  const int cursor_joystick_yaxis = preferences::joystick_num_cursor_yaxis();
372  const int cursor_yaxis = preferences::joystick_cursor_yaxis_num();
373 
374  const std::pair<int, int> values = get_axis_pair(cursor_joystick_xaxis, cursor_xaxis, cursor_joystick_yaxis, cursor_yaxis);
375 
376  const int x_axis = values.first;
377  const int y_axis = values.second;
378 
379  const double angle = (atan2(
380  static_cast<double>(y_axis)
381  , static_cast<double>(x_axis))) * 180.0 / pi<double>();
382 
383  return angle;
384 }
385 
386 
387 const map_location joystick_manager::get_next_hex(int x_axis, int y_axis, map_location loc) {
388 
390 
391  if (x_axis == 0) return (y_axis > 0) ? get_direction(loc, SOUTH) : get_direction(loc, NORTH);
392  if (y_axis == 0) return (x_axis > 0) ? get_direction(loc, EAST) : get_direction(loc, WEST);
393  const double angle = (atan2(
394  static_cast<double>(y_axis)
395  , static_cast<double>(x_axis))) * 180.0 / pi<double>();
396 
397  if (angle < -112.5 && angle > -157.5)
398  new_loc = get_direction(loc, NORTH_WEST);
399 
400  if (angle < -67.5 && angle > -112.5)
401  new_loc = get_direction(loc, NORTH);
402 
403  if (angle < -22.5 && angle > -67.5)
404  new_loc = get_direction(loc, NORTH_EAST);
405 
406  if (angle < 22.5 && angle > -22.5 )
407  new_loc = get_direction(loc, EAST);
408 
409  if (angle > 22.5 && angle < 67.5 )
410  new_loc = get_direction(loc, SOUTH_EAST);
411 
412  if (angle > 67.5 && angle < 113.5)
413  new_loc = get_direction(loc, SOUTH);
414 
415  if (angle > 113.5 && angle < 158.5)
416  new_loc = get_direction(loc, SOUTH_WEST);
417 
418  if (angle > 158.5 || angle < -157.5)
419  new_loc = get_direction(loc, WEST);
420 
421  return new_loc;
422 }
423 
int joystick_mouse_xaxis_num()
int joystick_thrustb_axis_num()
std::pair< int, int > get_axis_pair(int joystick_xaxis, int xaxis, int joystick_yaxis, int yaxis)
Definition: joystick.cpp:227
int joystick_mouse_yaxis_num()
static bool attached(const std::vector< SDL_Joystick * > &joysticks, const size_t index)
Definition: joystick.cpp:39
int joystick_num_mouse_xaxis()
int get_axis(int joystick_axis, int axis)
Definition: joystick.cpp:252
int joystick_thrusta_axis_num()
int joystick_num_cursor_yaxis()
bool update_highlighted_hex(map_location &highlighted_hex)
Used for absolute movement of the cursor.
Definition: joystick.cpp:299
bool is_odd(T num)
Definition: util.hpp:37
int joystick_thrustb_deadzone()
int joystick_num_mouse_yaxis()
int joystick_num_thrustb_axis()
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
int joystick_num_scroll_xaxis()
int joystick_num_cursor_xaxis()
int round_double(double d)
Definition: util.hpp:67
std::pair< double, double > get_scroll_axis_pair()
Definition: joystick.cpp:153
static lg::log_domain log_joystick("joystick")
GLboolean GLenum GLenum GLvoid * values
Definition: glew.h:3799
int joystick_cursor_yaxis_num()
int joystick_thrusta_deadzone()
bool joystick_support_enabled()
#define LOG_JOY
Definition: joystick.cpp:23
int joystick_scroll_yaxis_num()
std::pair< double, double > get_polar_coordinates(int joystick_xaxis, int xaxis, int joystick_yaxis, int yaxis)
TODO fendrin.
Definition: joystick.cpp:216
GLsizei const GLfloat * value
Definition: glew.h:1817
double get_thrusta_axis()
TODO fendrin.
Definition: joystick.cpp:182
static const map_location & null_location()
Definition: location.hpp:195
int joystick_scroll_xaxis_num()
double get_angle()
TODO fendrin.
Definition: joystick.cpp:366
Encapsulates the map of the game.
Definition: location.hpp:38
int joystick_num_thrusta_axis()
const map_location get_direction(const map_location &loc, joystick_manager::DIRECTION direction)
Definition: joystick.cpp:346
std::vector< SDL_Joystick * > joysticks_
Definition: joystick.hpp:95
double get_thrustb_axis()
TODO fendrin.
Definition: joystick.cpp:194
GLuint index
Definition: glew.h:1782
size_t i
Definition: function.cpp:1057
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
int joystick_cursor_xaxis_num()
int joystick_cursor_threshold()
#define ERR_JOY
Definition: joystick.cpp:22
GLdouble angle
Definition: glew.h:6979
Standard logging facilities (interface).
int joystick_scroll_deadzone()
static const char * name(const std::vector< SDL_Joystick * > &joysticks, const size_t index)
Definition: joystick.cpp:46
int joystick_mouse_deadzone()
int joystick_cursor_deadzone()
const map_location get_next_hex(int x_axis, int y_axis, map_location old_hex)
Definition: joystick.cpp:387
int joystick_num_scroll_yaxis()
std::pair< double, double > get_mouse_axis_pair()
TODO fendrin.
Definition: joystick.cpp:119
std::pair< double, double > get_cursor_polar_coordinates()
TODO fendrin.
Definition: joystick.cpp:206
bool is_even(T num)
Definition: util.hpp:34
GLclampf f
Definition: glew.h:3024