joystick.cpp

Go to the documentation of this file.
00001 /* $Id: joystick.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2011 - 2012 by Fabian Mueller
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #include "joystick.hpp"
00017 #include "preferences.hpp"
00018 #include "log.hpp"
00019 
00020 #define PI 3.14159265
00021 
00022 static lg::log_domain log_joystick("joystick");
00023 #define ERR_JOY LOG_STREAM(err, log_joystick)
00024 #define LOG_JOY LOG_STREAM(info, log_joystick)
00025 #define DBG_JOY LOG_STREAM(debug, log_joystick)
00026 
00027 joystick_manager::joystick_manager()
00028     : joysticks_()
00029     , joystick_area_(0)
00030     , counter_(0)
00031 {
00032     init();
00033 }
00034 
00035 joystick_manager::~joystick_manager() {
00036     close();
00037 }
00038 
00039 bool joystick_manager::close() {
00040     if(SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
00041         return true;
00042 
00043     int joysticks = joysticks_.size();
00044     bool all_closed = true;
00045 
00046     for (int i = 0; i<joysticks; i++)  {
00047         if (SDL_JoystickOpened(i)) {
00048             SDL_JoystickClose(joysticks_[i]);
00049             LOG_JOY << "Closed Joystick" << i;
00050             LOG_JOY << "Name: " << SDL_JoystickName(i);
00051         } else {
00052             ERR_JOY << "Joystick" << i << " closing failed.";
00053             all_closed = false;
00054         }
00055     }
00056 
00057     joysticks_.clear();
00058     return all_closed;
00059 }
00060 
00061 bool joystick_manager::init() {
00062 
00063     close();
00064 
00065     if (!preferences::joystick_support_enabled()) {
00066         LOG_JOY << "Joystick support is disabled.";
00067         return false;
00068     }
00069 
00070     LOG_JOY << "Initializing joysticks...\n";
00071     if(SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
00072         if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
00073             return false;
00074 
00075     joysticks_.clear();
00076 
00077     int joysticks = SDL_NumJoysticks();
00078     if (joysticks == 0) return false;
00079 
00080     SDL_JoystickEventState(SDL_ENABLE);
00081 
00082     bool joystick_found = false;
00083     for (int i = 0; i<joysticks; i++) {
00084         joysticks_.resize(i+1);
00085         joysticks_[i] = SDL_JoystickOpen(i);
00086 
00087         if (joysticks_[i] && SDL_JoystickOpened(i)) {
00088 
00089             joystick_found = true;
00090 
00091             LOG_JOY << "Opened Joystick" << i;
00092             LOG_JOY << "Name: " << SDL_JoystickName(i);
00093             LOG_JOY << "Number of Axes: " << SDL_JoystickNumAxes(joysticks_[i]);
00094             LOG_JOY << "Number of Buttons: " << SDL_JoystickNumButtons(joysticks_[i]);
00095             LOG_JOY << "Number of Balls: " << SDL_JoystickNumBalls(joysticks_[i]);
00096             LOG_JOY << "Number of Hats: ", SDL_JoystickNumHats(joysticks_[i]);
00097         } else {
00098             ERR_JOY << "Couldn't open Joystick" << i;
00099         }
00100     }
00101     return joystick_found;
00102 }
00103 
00104 std::pair<double, double> joystick_manager::get_mouse_axis_pair() {
00105 
00106     const int mouse_joystick_x = preferences::joystick_num_mouse_xaxis();
00107     const int mouse_xaxis = preferences::joystick_mouse_xaxis_num();
00108 
00109     const int mouse_joystick_y = preferences::joystick_num_mouse_yaxis();
00110     const int mouse_yaxis = preferences::joystick_mouse_yaxis_num();
00111 
00112     std::pair<int, int> values;
00113     double thrust;
00114     {
00115         values = get_axis_pair(mouse_joystick_x, mouse_xaxis, mouse_joystick_y, mouse_yaxis);
00116         thrust = get_thrusta_axis();
00117     }
00118 
00119     const int radius = round_double(sqrt(pow(values.first, 2.0f) + pow(values.second, 2.0f)));
00120     const int deadzone = preferences::joystick_mouse_deadzone();
00121     const double multiplier = 1.0 + thrust;
00122 
00123     if (deadzone > radius)
00124         return std::make_pair(0.0, 0.0);
00125 
00126     // TODO do some math to normalize over the value - deadzone.
00127     //const double relation = abs( (double)values.first / (double)values.second );
00128     //const int range_x = values.first - round_double(relation * deadzone);
00129     //const int range_y = values.second - ((1.0 - relation) * deadzone);
00130     //double x_value = ((double)(values.first - deadzone) / (double)(32768 - deadzone)) *
00131 
00132     return std::make_pair(
00133               ((static_cast<double>(values.first)) / 32768.0) * multiplier
00134             , ((static_cast<double>(values.second)) / 32768.0) * multiplier );
00135 
00136 }
00137 
00138 std::pair<double, double> joystick_manager::get_scroll_axis_pair() {
00139 
00140     if (!preferences::joystick_support_enabled()) return std::make_pair(0.0, 0.0);
00141 
00142     const int scroll_joystick_x = preferences::joystick_num_scroll_xaxis();
00143     const int scroll_axis = preferences::joystick_scroll_xaxis_num();
00144 
00145     const int scroll_joystick_y = preferences::joystick_num_scroll_yaxis();
00146     const int scroll_yaxis = preferences::joystick_scroll_yaxis_num();
00147 
00148     std::pair<int, int> values;
00149     double thrust;
00150     {
00151         values = get_axis_pair(scroll_joystick_x, scroll_axis, scroll_joystick_y, scroll_yaxis);
00152         thrust = get_thrusta_axis();
00153     }
00154 
00155     const int radius = round_double(sqrt(pow(values.first, 2.0f) + pow(values.second, 2.0f)));
00156     const int deadzone = preferences::joystick_scroll_deadzone();
00157     const double multiplier = 1.0 + thrust;
00158 
00159     if (deadzone > radius)
00160         return std::make_pair(0.0, 0.0);
00161 
00162     return std::make_pair(
00163               ((static_cast<double>(values.first)) / 32768.0) * multiplier
00164             , ((static_cast<double>(values.second)) / 32768.0) * multiplier );
00165 }
00166 
00167 double joystick_manager::get_thrusta_axis() {
00168     if (!preferences::joystick_support_enabled()) return 0.0;
00169 
00170     const int thrust_joystick_x = preferences::joystick_num_thrusta_axis();
00171     const int thrust_axis_x = preferences::joystick_thrusta_axis_num();
00172     const int thrust_deadzone = preferences::joystick_thrusta_deadzone();
00173 
00174     const int value = get_axis(thrust_joystick_x, thrust_axis_x) + 32768;
00175     if (value < thrust_deadzone) return 0.0;
00176     return static_cast<double>(value) / 65536.0;
00177 }
00178 
00179 double joystick_manager::get_thrustb_axis() {
00180     if (!preferences::joystick_support_enabled()) return 0.0;
00181 
00182     const int thrustb_joystick = preferences::joystick_num_thrustb_axis();
00183     const int thrustb_axis = preferences::joystick_thrustb_axis_num();
00184     const int thrustb_deadzone = preferences::joystick_thrustb_deadzone();
00185 
00186     const int value = get_axis(thrustb_joystick, thrustb_axis) + 32768;
00187     if (value < thrustb_deadzone) return 0.0;
00188     return static_cast<double>(value) / 65536.0;
00189 }
00190 
00191 std::pair<double, double> joystick_manager::get_cursor_polar_coordinates() {
00192     const int cursor_joystick_xaxis = preferences::joystick_num_cursor_xaxis();
00193     const int cursor_xaxis = preferences::joystick_cursor_xaxis_num();
00194 
00195     const int cursor_joystick_yaxis = preferences::joystick_num_cursor_yaxis();
00196     const int cursor_yaxis = preferences::joystick_cursor_yaxis_num();
00197 
00198     return get_polar_coordinates(cursor_joystick_xaxis, cursor_xaxis, cursor_joystick_yaxis, cursor_yaxis);
00199 }
00200 
00201 std::pair<double, double> joystick_manager::get_polar_coordinates(int joystick_xaxis, int xaxis, int joystick_yaxis, int yaxis) {
00202 
00203     const std::pair<int, int> values = get_axis_pair(joystick_xaxis, xaxis, joystick_yaxis, yaxis);
00204     const double radius = (sqrt(pow(values.first, 2.0f) + pow(values.second, 2.0f))) / 32768.0;
00205     const double angle = (atan2(
00206               static_cast<double>(values.second)
00207             , static_cast<double>(values.first))) * 180.0 / PI;
00208 
00209     return std::make_pair(radius, angle);
00210 }
00211 
00212 std::pair<int, int> joystick_manager::get_axis_pair(int joystick_xaxis, int xaxis, int joystick_yaxis, int yaxis) {
00213 
00214     if(!SDL_WasInit(SDL_INIT_JOYSTICK))
00215         return std::make_pair(0, 0);
00216 
00217     int x_axis = 0, y_axis = 0;
00218     bool get_xaxis = false, get_yaxis = false;
00219 
00220     if(SDL_JoystickOpened(joystick_xaxis))
00221         if(SDL_JoystickNumAxes(joysticks_[joystick_xaxis]) > xaxis)
00222             get_xaxis = true;
00223 
00224     if(SDL_JoystickOpened(joystick_yaxis))
00225         if(SDL_JoystickNumAxes(joysticks_[joystick_yaxis]) > yaxis)
00226             get_yaxis = true;
00227 
00228     //TODO Does the block prevent the commands from being interrupted?
00229     //We want the readings to be from a similar time slice.
00230     {
00231             if (get_xaxis) x_axis = SDL_JoystickGetAxis(joysticks_[joystick_xaxis], xaxis);
00232             if (get_yaxis) y_axis = SDL_JoystickGetAxis(joysticks_[joystick_yaxis], yaxis);
00233     }
00234     return std::make_pair(x_axis, y_axis);
00235 }
00236 
00237 int joystick_manager::get_axis(int joystick_axis, int axis) {
00238     if(!SDL_WasInit(SDL_INIT_JOYSTICK))
00239         return 0;
00240 
00241     if(SDL_JoystickOpened(joystick_axis))
00242         if(SDL_JoystickNumAxes(joysticks_[joystick_axis]) > axis)
00243             return SDL_JoystickGetAxis(joysticks_[joystick_axis], axis);
00244     return 0;
00245 }
00246 
00247 
00248 bool joystick_manager::update_highlighted_hex(map_location& highlighted_hex, const map_location& selected_hex) {
00249 
00250     const int cursor_joystick_xaxis = preferences::joystick_num_cursor_xaxis();
00251     const int cursor_xaxis = preferences::joystick_cursor_xaxis_num();
00252 
00253     const int cursor_joystick_yaxis = preferences::joystick_num_cursor_yaxis();
00254     const int cursor_yaxis = preferences::joystick_cursor_yaxis_num();
00255 
00256     const std::pair<int, int> values = get_axis_pair(cursor_joystick_xaxis, cursor_xaxis, cursor_joystick_yaxis, cursor_yaxis);
00257 
00258     const int x_axis = values.first;
00259     const int y_axis = values.second;
00260 
00261     //const int radius = round_double(sqrt(pow(x_axis, 2.0f) + pow(y_axis, 2.0f)));
00262 
00263 //  const int deadzone = preferences::joystick_cursor_deadzone();
00264     //const int threshold2 = 10*threshold;
00265     //const int max = 100000;
00266 
00267     //const bool greater_deadzone = radius > deadzone;
00268     //const bool greater_threshold2 = radius > threshold2;
00269 
00270     int x = selected_hex.x + round_double(x_axis / 3200);
00271     int y = selected_hex.y + round_double(y_axis / 3200);
00272     highlighted_hex = map_location(x,y);
00273 
00274     //if (!greater_threshold) {
00275     //  counter_ = 0;
00276     //  joystick_area_ = 0;
00277     //  return false;
00278     //}
00279 
00280     return true;
00281 }
00282 
00283 
00284 bool joystick_manager::update_highlighted_hex(map_location& highlighted_hex) {
00285 
00286     const int cursor_joystick_xaxis = preferences::joystick_num_cursor_xaxis();
00287     const int cursor_xaxis = preferences::joystick_cursor_xaxis_num();
00288 
00289     const int cursor_joystick_yaxis = preferences::joystick_num_cursor_yaxis();
00290     const int cursor_yaxis = preferences::joystick_cursor_yaxis_num();
00291 
00292     const std::pair<int, int> values = get_axis_pair(cursor_joystick_xaxis, cursor_xaxis, cursor_joystick_yaxis, cursor_yaxis);
00293 
00294     const int x_axis = values.first;
00295     const int y_axis = values.second;
00296 
00297     const int radius = round_double(sqrt(pow(x_axis, 2.0f) + pow(y_axis, 2.0f)));
00298 
00299     const int deadzone = preferences::joystick_cursor_deadzone();
00300     const int threshold = deadzone + preferences::joystick_cursor_threshold();
00301     //TODO fendrin take max from preferences as well
00302     const int max = 100000;
00303 
00304     const bool greater_deadzone = radius > deadzone;
00305     const bool greater_threshold2 = radius > threshold;
00306 
00307     if (!greater_deadzone) {
00308         counter_ = 0;
00309         joystick_area_ = 0;
00310         return false;
00311     } else {
00312         if (joystick_area_ == 0) {
00313             highlighted_hex = get_next_hex(x_axis, y_axis, highlighted_hex);
00314         }
00315         if (!greater_threshold2) {
00316             joystick_area_ = 1;
00317         } else {
00318             joystick_area_ = 2;
00319             counter_ += radius;
00320             if (counter_ > max) {
00321                 counter_ -= max;
00322                 highlighted_hex = get_next_hex(x_axis, y_axis, highlighted_hex);
00323                 return true;
00324             } else return false;
00325         }
00326     }
00327 
00328     return true;
00329 }
00330 
00331 const map_location joystick_manager::get_direction(const map_location& loc, joystick_manager::DIRECTION direction) {
00332 
00333     int x = loc.x;
00334     int y = loc.y;
00335 
00336     switch(direction) {
00337         case NORTH:      return map_location(x, y - 1);
00338         case SOUTH:      return map_location(x, y + 1);
00339         case SOUTH_EAST: return map_location(x + 1, y + (1+is_odd(x))/2 );
00340         case SOUTH_WEST: return map_location(x - 1, y + (1+is_odd(x))/2 );
00341         case NORTH_EAST: return map_location(x + 1, y - (1+is_even(x))/2 );
00342         case NORTH_WEST: return map_location(x - 1, y - (1+is_even(x))/2 );
00343         case WEST:       return map_location(x - 1, y);
00344         case EAST:       return map_location(x + 1, y);
00345         default:
00346             assert(false);
00347             return map_location();
00348     }
00349 }
00350 
00351 double joystick_manager::get_angle() {
00352 
00353     const int cursor_joystick_xaxis = preferences::joystick_num_cursor_xaxis();
00354     const int cursor_xaxis = preferences::joystick_cursor_xaxis_num();
00355 
00356     const int cursor_joystick_yaxis = preferences::joystick_num_cursor_yaxis();
00357     const int cursor_yaxis = preferences::joystick_cursor_yaxis_num();
00358 
00359     const std::pair<int, int> values = get_axis_pair(cursor_joystick_xaxis, cursor_xaxis, cursor_joystick_yaxis, cursor_yaxis);
00360 
00361     const int x_axis = values.first;
00362     const int y_axis = values.second;
00363 
00364     const double angle = (atan2(
00365                   static_cast<double>(y_axis)
00366                 , static_cast<double>(x_axis))) * 180.0 / PI;
00367 
00368     return angle;
00369 }
00370 
00371 
00372 const map_location joystick_manager::get_next_hex(int x_axis, int y_axis, map_location loc)  {
00373 
00374     map_location new_loc = map_location::null_location;
00375 
00376     if (x_axis == 0) return (y_axis > 0) ? get_direction(loc, SOUTH) : get_direction(loc, NORTH);
00377     if (y_axis == 0) return (x_axis > 0) ? get_direction(loc, EAST) : get_direction(loc, WEST);
00378     const double angle = (atan2(
00379               static_cast<double>(y_axis)
00380             , static_cast<double>(x_axis))) * 180.0 / PI;
00381 
00382     if (angle < -112.5 && angle > -157.5)
00383         new_loc = get_direction(loc, NORTH_WEST);
00384 
00385     if (angle < -67.5 && angle > -112.5)
00386         new_loc = get_direction(loc, NORTH);
00387 
00388     if (angle < -22.5 && angle > -67.5)
00389         new_loc = get_direction(loc, NORTH_EAST);
00390 
00391     if (angle < 22.5 && angle > -22.5 )
00392         new_loc = get_direction(loc, EAST);
00393 
00394     if (angle > 22.5 && angle < 67.5 )
00395         new_loc = get_direction(loc, SOUTH_EAST);
00396 
00397     if (angle > 67.5 && angle < 113.5)
00398         new_loc = get_direction(loc, SOUTH);
00399 
00400     if (angle > 113.5 && angle < 158.5)
00401         new_loc = get_direction(loc, SOUTH_WEST);
00402 
00403     if (angle > 158.5 || angle < -157.5)
00404         new_loc = get_direction(loc, WEST);
00405 
00406     return new_loc;
00407 }
00408 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:03 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs