Moved some joystick related messages into log_debug, added help message for manual...
[supertux.git] / src / control / game_controller_manager.cpp
1 //  SuperTux
2 //  Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include "control/game_controller_manager.hpp"
18
19 #include <algorithm>
20
21 #include "control/input_manager.hpp"
22 #include "util/log.hpp"
23
24 GameControllerManager::GameControllerManager(InputManager* parent) :
25   m_parent(parent),
26   m_deadzone(8000),
27   m_game_controllers(),
28   m_stick_state(),
29   m_button_state()
30 {
31 }
32
33 GameControllerManager::~GameControllerManager()
34 {
35   for(auto con : m_game_controllers)
36   {
37     SDL_GameControllerClose(con);
38   }
39 }
40
41 void
42 GameControllerManager::process_button_event(const SDL_ControllerButtonEvent& ev)
43 {
44   //log_info << "button event: " << static_cast<int>(ev.button) << " " << static_cast<int>(ev.state) << std::endl;
45   auto controller = m_parent->get_controller();
46   auto set_control = [this, &controller](Controller::Control control, bool value)
47   {
48     m_button_state[control] = value;
49     controller->set_control(control, m_button_state[control] || m_stick_state[control]);
50   };
51   switch(ev.button)
52   {
53     case SDL_CONTROLLER_BUTTON_A:
54       set_control(Controller::JUMP, ev.state);
55       set_control(Controller::MENU_SELECT, ev.state);
56       break;
57
58     case SDL_CONTROLLER_BUTTON_B:
59       set_control(Controller::MENU_BACK, ev.state);
60       break;
61
62     case SDL_CONTROLLER_BUTTON_X:
63       set_control(Controller::ACTION, ev.state);
64       break;
65
66     case SDL_CONTROLLER_BUTTON_Y:
67       break;
68
69     case SDL_CONTROLLER_BUTTON_BACK:
70       break;
71
72     case SDL_CONTROLLER_BUTTON_GUIDE:
73       set_control(Controller::CONSOLE, ev.state);
74       break;
75
76     case SDL_CONTROLLER_BUTTON_START:
77       set_control(Controller::PAUSE_MENU, ev.state);
78       break;
79
80     case SDL_CONTROLLER_BUTTON_LEFTSTICK:
81       break;
82
83     case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
84       break;
85
86     case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
87       set_control(Controller::PEEK_LEFT, ev.state);
88       break;
89
90     case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
91       set_control(Controller::PEEK_RIGHT, ev.state);
92       break;
93
94     case SDL_CONTROLLER_BUTTON_DPAD_UP:
95       set_control(Controller::UP, ev.state);
96       break;
97
98     case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
99       set_control(Controller::DOWN, ev.state);
100       break;
101
102     case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
103       set_control(Controller::LEFT, ev.state);
104       break;
105
106     case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
107       set_control(Controller::RIGHT, ev.state);
108       break;
109
110     default:
111       break;
112   }
113 }
114
115 void
116 GameControllerManager::process_axis_event(const SDL_ControllerAxisEvent& ev)
117 {
118   // FIXME: buttons and axis are fighting for control ownership, need
119   // to OR the values together
120
121   //log_info << "axis event: " << static_cast<int>(ev.axis) << " " << ev.value << std::endl;
122   auto controller = m_parent->get_controller();
123   auto set_control = [this, &controller](Controller::Control control, bool value)
124   {
125     m_stick_state[control] = value;
126     controller->set_control(control, m_button_state[control] || m_stick_state[control]);
127   };
128
129   auto axis2button = [this, &set_control](int value,
130                                          Controller::Control control_left, Controller::Control control_right)
131     {
132       if (value < -m_deadzone)
133       {
134         set_control(control_left, true);
135         set_control(control_right, false);
136       }
137       else if (value > m_deadzone)
138       {
139         set_control(control_left, false);
140         set_control(control_right, true);
141       }
142       else
143       {
144         set_control(control_left, false);
145         set_control(control_right, false);
146       }
147     };
148
149   switch(ev.axis)
150   {
151     case SDL_CONTROLLER_AXIS_LEFTX:
152       axis2button(ev.value, Controller::LEFT, Controller::RIGHT);
153       break;
154
155     case SDL_CONTROLLER_AXIS_LEFTY:
156       axis2button(ev.value, Controller::UP, Controller::DOWN);
157       break;
158
159     case SDL_CONTROLLER_AXIS_RIGHTX:
160       axis2button(ev.value, Controller::PEEK_LEFT, Controller::PEEK_RIGHT);
161       break;
162
163     case SDL_CONTROLLER_AXIS_RIGHTY:
164       axis2button(ev.value, Controller::PEEK_UP, Controller::PEEK_DOWN);
165       break;
166
167     case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
168       break;
169
170     case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
171       break;
172
173     default:
174       break;
175   }
176 }
177
178 void
179 GameControllerManager::on_controller_added(int joystick_index)
180 {
181   if (!SDL_IsGameController(joystick_index))
182   {
183     log_warning << "joystick is not a game controller, ignoring: " << joystick_index << std::endl;
184   }
185   else
186   {
187     SDL_GameController* game_controller = SDL_GameControllerOpen(joystick_index);
188     if (!game_controller)
189     {
190       log_warning << "failed to open game_controller: " << joystick_index
191                   << ": " << SDL_GetError() << std::endl;
192     }
193     else
194     {
195       m_game_controllers.push_back(game_controller);
196     }
197   }
198 }
199
200 void
201 GameControllerManager::on_controller_removed(int instance_id)
202 {
203   for(auto& controller : m_game_controllers)
204   {
205     SDL_Joystick* joy = SDL_GameControllerGetJoystick(controller);
206     SDL_JoystickID id = SDL_JoystickInstanceID(joy);
207     if (id == instance_id)
208     {
209       SDL_GameControllerClose(controller);
210       controller = nullptr;
211     }
212   }
213
214   m_game_controllers.erase(std::remove(m_game_controllers.begin(), m_game_controllers.end(), nullptr),
215                            m_game_controllers.end());
216 }
217
218 /* EOF */