2 // Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
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.
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.
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/>.
17 #include "control/game_controller_manager.hpp"
21 #include "control/input_manager.hpp"
22 #include "util/log.hpp"
24 GameControllerManager::GameControllerManager(InputManager* parent) :
33 GameControllerManager::~GameControllerManager()
35 for(auto con : m_game_controllers)
37 SDL_GameControllerClose(con);
42 GameControllerManager::process_button_event(const SDL_ControllerButtonEvent& ev)
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)
48 m_button_state[control] = value;
49 controller->set_control(control, m_button_state[control] || m_stick_state[control]);
53 case SDL_CONTROLLER_BUTTON_A:
54 set_control(Controller::JUMP, ev.state);
55 set_control(Controller::MENU_SELECT, ev.state);
58 case SDL_CONTROLLER_BUTTON_B:
59 set_control(Controller::MENU_BACK, ev.state);
62 case SDL_CONTROLLER_BUTTON_X:
63 set_control(Controller::ACTION, ev.state);
66 case SDL_CONTROLLER_BUTTON_Y:
69 case SDL_CONTROLLER_BUTTON_BACK:
70 set_control(Controller::CONSOLE, ev.state);
73 case SDL_CONTROLLER_BUTTON_GUIDE:
74 set_control(Controller::CHEAT_MENU, ev.state);
77 case SDL_CONTROLLER_BUTTON_START:
78 set_control(Controller::PAUSE_MENU, ev.state);
81 case SDL_CONTROLLER_BUTTON_LEFTSTICK:
84 case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
87 case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
88 set_control(Controller::PEEK_LEFT, ev.state);
91 case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
92 set_control(Controller::PEEK_RIGHT, ev.state);
95 case SDL_CONTROLLER_BUTTON_DPAD_UP:
96 set_control(Controller::UP, ev.state);
99 case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
100 set_control(Controller::DOWN, ev.state);
103 case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
104 set_control(Controller::LEFT, ev.state);
107 case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
108 set_control(Controller::RIGHT, ev.state);
117 GameControllerManager::process_axis_event(const SDL_ControllerAxisEvent& ev)
119 // FIXME: buttons and axis are fighting for control ownership, need
120 // to OR the values together
122 //log_info << "axis event: " << static_cast<int>(ev.axis) << " " << ev.value << std::endl;
123 auto controller = m_parent->get_controller();
124 auto set_control = [this, &controller](Controller::Control control, bool value)
126 m_stick_state[control] = value;
127 controller->set_control(control, m_button_state[control] || m_stick_state[control]);
130 auto axis2button = [this, &set_control](int value,
131 Controller::Control control_left, Controller::Control control_right)
133 if (value < -m_deadzone)
135 set_control(control_left, true);
136 set_control(control_right, false);
138 else if (value > m_deadzone)
140 set_control(control_left, false);
141 set_control(control_right, true);
145 set_control(control_left, false);
146 set_control(control_right, false);
152 case SDL_CONTROLLER_AXIS_LEFTX:
153 axis2button(ev.value, Controller::LEFT, Controller::RIGHT);
156 case SDL_CONTROLLER_AXIS_LEFTY:
157 axis2button(ev.value, Controller::UP, Controller::DOWN);
160 case SDL_CONTROLLER_AXIS_RIGHTX:
161 axis2button(ev.value, Controller::PEEK_LEFT, Controller::PEEK_RIGHT);
164 case SDL_CONTROLLER_AXIS_RIGHTY:
165 axis2button(ev.value, Controller::PEEK_UP, Controller::PEEK_DOWN);
168 case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
171 case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
180 GameControllerManager::on_controller_added(int joystick_index)
182 if (!SDL_IsGameController(joystick_index))
184 log_warning << "joystick is not a game controller, ignoring: " << joystick_index << std::endl;
188 SDL_GameController* game_controller = SDL_GameControllerOpen(joystick_index);
189 if (!game_controller)
191 log_warning << "failed to open game_controller: " << joystick_index
192 << ": " << SDL_GetError() << std::endl;
196 m_game_controllers.push_back(game_controller);
202 GameControllerManager::on_controller_removed(int instance_id)
204 for(auto& controller : m_game_controllers)
206 SDL_Joystick* joy = SDL_GameControllerGetJoystick(controller);
207 SDL_JoystickID id = SDL_JoystickInstanceID(joy);
208 if (id == instance_id)
210 SDL_GameControllerClose(controller);
211 controller = nullptr;
215 m_game_controllers.erase(std::remove(m_game_controllers.begin(), m_game_controllers.end(), nullptr),
216 m_game_controllers.end());