MXVK Vulkan Framework 0.24.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
mxvk_controller.cpp
Go to the documentation of this file.
1/**
2 * @file mxvk_controller.cpp
3 * @brief Implementation of mxvk::VK_Joystick and mxvk::VK_Controller SDL3 wrappers.
4 */
5
7
9
10#include <SDL3/SDL_stdinc.h>
11
12namespace mxvk {
13
14 VK_Joystick::VK_Joystick() = default;
15
17 close();
18 }
19
21 int count = 0;
22 SDL_JoystickID *ids = SDL_GetJoysticks(&count);
23 if (ids != nullptr) {
24 SDL_free(ids);
25 }
26 return count;
27 }
28
29 bool VK_Joystick::open(const int index) {
30 close();
31
32 int count = 0;
33 SDL_JoystickID *ids = SDL_GetJoysticks(&count);
34 if (ids == nullptr || index < 0 || index >= count) {
35 if (ids != nullptr) {
36 SDL_free(ids);
37 }
38 return false;
39 }
40
41 const SDL_JoystickID openedInstanceId = ids[index];
42 SDL_free(ids);
43
44 stick = SDL_OpenJoystick(openedInstanceId);
45 if (stick == nullptr) {
46 return false;
47 }
48
49 deviceIndex = index;
50 instanceId = openedInstanceId;
51 SDL_SetJoystickEventsEnabled(true);
52 return true;
53 }
54
55 std::string VK_Joystick::name() const {
56 if (stick != nullptr) {
57 const char *device_name = SDL_GetJoystickName(stick);
58 if (device_name != nullptr) {
59 return device_name;
60 }
61 }
62 return "Joystick Not Opened.";
63 }
64
66 if (stick != nullptr) {
67 SDL_CloseJoystick(stick);
68 }
69
70 stick = nullptr;
71 deviceIndex = -1;
72 instanceId = 0;
73 }
74
75 std::optional<SDL_Joystick *> VK_Joystick::handle() const {
76 if (stick != nullptr) {
77 return stick;
78 }
79 return std::nullopt;
80 }
81
82 SDL_Joystick *VK_Joystick::unwrap() const {
83 if (stick != nullptr) {
84 return stick;
85 }
86 throw mxvk::Exception("Invalid joystick handle");
87 }
88
90 return deviceIndex;
91 }
92
93 bool VK_Joystick::getButton(const int button) const {
94 if (stick == nullptr) {
95 return false;
96 }
97 return SDL_GetJoystickButton(stick, button);
98 }
99
100 Uint8 VK_Joystick::getHat(const int hat) const {
101 if (stick == nullptr) {
102 return 0;
103 }
104 return SDL_GetJoystickHat(stick, hat);
105 }
106
107 Sint16 VK_Joystick::getAxis(const int axis) const {
108 if (stick == nullptr) {
109 return 0;
110 }
111 return SDL_GetJoystickAxis(stick, axis);
112 }
113
115 if (stick == nullptr) {
116 return 0;
117 }
118 const int count = SDL_GetNumJoystickButtons(stick);
119 return count < 0 ? 0 : count;
120 }
121
123 if (stick == nullptr) {
124 return 0;
125 }
126 const int count = SDL_GetNumJoystickHats(stick);
127 return count < 0 ? 0 : count;
128 }
129
131 if (stick == nullptr) {
132 return 0;
133 }
134 const int count = SDL_GetNumJoystickAxes(stick);
135 return count < 0 ? 0 : count;
136 }
137
139
141 close();
142 }
143
145 int count = 0;
146 SDL_JoystickID *ids = SDL_GetGamepads(&count);
147 if (ids != nullptr) {
148 SDL_free(ids);
149 }
150 return count;
151 }
152
153 bool VK_Controller::openByInstanceId(const SDL_JoystickID newInstanceId, const int index_hint) {
154 close();
155
156 stick = SDL_OpenGamepad(newInstanceId);
157 if (stick == nullptr) {
158 return false;
159 }
160
161 deviceIndex = index_hint;
162 instanceId = newInstanceId;
163 SDL_SetGamepadEventsEnabled(true);
164 return true;
165 }
166
167 bool VK_Controller::open(const int index) {
168 int count = 0;
169 SDL_JoystickID *ids = SDL_GetGamepads(&count);
170 if (ids == nullptr || index < 0 || index >= count) {
171 if (ids != nullptr) {
172 SDL_free(ids);
173 }
174 return false;
175 }
176
177 const SDL_JoystickID openedInstanceId = ids[index];
178 SDL_free(ids);
179 return openByInstanceId(openedInstanceId, index);
180 }
181
182 std::string VK_Controller::name() const {
183 if (stick != nullptr) {
184 const char *device_name = SDL_GetGamepadName(stick);
185 if (device_name != nullptr) {
186 return device_name;
187 }
188 }
189 return "Controller Not Opened.";
190 }
191
193 if (stick != nullptr) {
194 SDL_CloseGamepad(stick);
195 }
196
197 stick = nullptr;
198 deviceIndex = -1;
199 instanceId = 0;
200 }
201
202 std::optional<SDL_Gamepad *> VK_Controller::handle() const {
203 if (stick != nullptr) {
204 return stick;
205 }
206 return std::nullopt;
207 }
208
209 SDL_Gamepad *VK_Controller::unwrap() const {
210 if (stick != nullptr) {
211 return stick;
212 }
213 throw mxvk::Exception("Invalid controller handle");
214 }
215
217 return deviceIndex;
218 }
219
220 bool VK_Controller::getButton(const SDL_GamepadButton button) const {
221 if (stick == nullptr) {
222 return false;
223 }
224 return SDL_GetGamepadButton(stick, button);
225 }
226
227 Uint8 VK_Controller::getHat(const int hat) const {
228 if (stick == nullptr) {
229 return 0;
230 }
231
232 SDL_Joystick *joystick = SDL_GetGamepadJoystick(stick);
233 if (joystick == nullptr) {
234 return 0;
235 }
236 return SDL_GetJoystickHat(joystick, hat);
237 }
238
239 Sint16 VK_Controller::getAxis(const SDL_GamepadAxis axis) const {
240 if (stick == nullptr) {
241 return 0;
242 }
243 return SDL_GetGamepadAxis(stick, axis);
244 }
245
247 return stick != nullptr && SDL_GamepadConnected(stick);
248 }
249
250 bool VK_Controller::connectEvent(SDL_Event &e) {
251 if (e.type == SDL_EVENT_GAMEPAD_ADDED) {
252 return openByInstanceId(e.gdevice.which);
253 }
254
255 if (e.type == SDL_EVENT_GAMEPAD_REMOVED) {
256 if (stick != nullptr && instanceId == e.gdevice.which) {
257 close();
258 }
259 return true;
260 }
261
262 return false;
263 }
264
265} // namespace mxvk
std::optional< SDL_Gamepad * > handle() const
Return the underlying SDL_Gamepad handle as an optional.
int controllerIndex() const
Return the device index this controller was opened with.
void close()
Close the controller handle if open.
Sint16 getAxis(SDL_GamepadAxis axis) const
Read the current axis value.
SDL_Gamepad * unwrap() const
Unwrap the SDL_Gamepad pointer, asserting it is open.
SDL_Gamepad * stick
Underlying SDL gamepad handle.
SDL_JoystickID instanceId
Stable SDL gamepad instance identifier.
bool active() const
Check whether the controller is currently usable.
int deviceIndex
Open index in the current gamepad list.
bool openByInstanceId(SDL_JoystickID instanceId, int index_hint=-1)
bool getButton(SDL_GamepadButton button) const
Test whether a mapped button is currently pressed.
VK_Controller()
Default constructor — device not yet opened.
bool connectEvent(SDL_Event &e)
Handle a device-added/removed event to maintain connection state.
Uint8 getHat(int hat) const
Read the position of a POV hat.
static int joysticks()
Return the number of connected joysticks/controllers.
~VK_Controller() noexcept
Destructor — closes the controller if open.
bool open(int index)
Open a gamepad by device index.
std::string name() const
Return the controller's name as reported by SDL.
SDL_JoystickID instanceId
Stable SDL joystick instance identifier.
VK_Joystick()
Default constructor — device not yet opened.
~VK_Joystick() noexcept
Destructor — closes the joystick if open.
SDL_Joystick * unwrap() const
Unwrap the SDL_Joystick pointer, asserting it is open.
bool getButton(int button) const
Test whether a button is currently pressed.
bool open(int index)
Open the joystick at the given device index.
Uint8 getHat(int hat) const
Read the position of a POV hat.
static int joysticks()
Return the number of connected joysticks.
int deviceIndex
Open index in the current joystick list.
int joystickIndex() const
Return the device index this joystick was opened with.
SDL_Joystick * stick
Underlying SDL joystick handle.
std::optional< SDL_Joystick * > handle() const
Return the underlying SDL_Joystick handle as an optional.
std::string name() const
Return the joystick's name as reported by SDL.
Sint16 getAxis(int axis) const
Read the current axis value.
void close()
Close the joystick handle if open.
SDL3 joystick and gamepad RAII wrappers.
Utilities for loading and saving PNG images.
Definition mxvk.hpp:30