1 /+
2 +            Copyright 2022 – 2024 Aya Partridge
3 +          Copyright 2018 - 2022 Michael D. Parker
4 + Distributed under the Boost Software License, Version 1.0.
5 +     (See accompanying file LICENSE_1_0.txt or copy at
6 +           http://www.boost.org/LICENSE_1_0.txt)
7 +/
8 module sdl.gamecontroller;
9 
10 import bindbc.sdl.config;
11 import bindbc.sdl.codegen;
12 
13 import sdl.joystick;
14 import sdl.rwops;
15 import sdl.sensor;
16 import sdl.stdinc: SDL_bool;
17 
18 struct SDL_GameController;
19 
20 static if(sdlSupport >= SDLSupport.v2_0_12){
21 	alias SDL_GameControllerType = uint;
22 	enum: SDL_GameControllerType{
23 		SDL_CONTROLLER_TYPE_UNKNOWN                         = 0,
24 		SDL_CONTROLLER_TYPE_XBOX360                         = 1,
25 		SDL_CONTROLLER_TYPE_XBOXONE                         = 2,
26 		SDL_CONTROLLER_TYPE_PS3                             = 3,
27 		SDL_CONTROLLER_TYPE_PS4                             = 4,
28 		SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO             = 5,
29 	}
30 	static if(sdlSupport >= SDLSupport.v2_0_14):
31 	enum: SDL_GameControllerType{
32 		SDL_CONTROLLER_TYPE_VIRTUAL                         = 6,
33 		SDL_CONTROLLER_TYPE_PS5                             = 7,
34 	}
35 	static if(sdlSupport >= SDLSupport.v2_0_16):
36 	enum: SDL_GameControllerType{
37 		SDL_CONTROLLER_TYPE_AMAZON_LUNA                     = 8,
38 		SDL_CONTROLLER_TYPE_GOOGLE_STADIA                   = 9,
39 	}
40 	static if(sdlSupport >= SDLSupport.v2_24):
41 	enum: SDL_GameControllerType{
42 		SDL_CONTROLLER_TYPE_NVIDIA_SHIELD                   = 10,
43 		SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT     = 11,
44 		SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT    = 12,
45 		SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR     = 13,
46 	}
47 	static if(sdlSupport >= SDLSupport.v2_30):
48 	enum: SDL_GameControllerType{
49 		SDL_CONTROLLER_TYPE_MAX                             = 14,
50 	}
51 }
52 
53 alias SDL_GameControllerBindType = uint;
54 enum: SDL_GameControllerBindType{
55 	SDL_CONTROLLER_BINDTYPE_NONE    = 0,
56 	SDL_CONTROLLER_BINDTYPE_BUTTON  = 1,
57 	SDL_CONTROLLER_BINDTYPE_AXIS    = 2,
58 	SDL_CONTROLLER_BINDTYPE_HAT     = 3,
59 }
60 
61 struct SDL_GameControllerButtonBind{
62 	SDL_GameControllerBindType bindType;
63 	union Value_{
64 		int button;
65 		int axis;
66 		struct Hat_{
67 			int hat;
68 			int hat_mask;
69 		}
70 		Hat_ hat;
71 	}
72 	Value_ value;
73 }
74 
75 alias SDL_GameControllerAxis = int;
76 enum: SDL_GameControllerAxis{
77 	SDL_CONTROLLER_AXIS_INVALID = -1,
78 	SDL_CONTROLLER_AXIS_LEFTX,
79 	SDL_CONTROLLER_AXIS_LEFTY,
80 	SDL_CONTROLLER_AXIS_RIGHTX,
81 	SDL_CONTROLLER_AXIS_RIGHTY,
82 	SDL_CONTROLLER_AXIS_TRIGGERLEFT,
83 	SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
84 	SDL_CONTROLLER_AXIS_MAX,
85 }
86 
87 alias SDL_GameControllerButton = int;
88 enum: SDL_GameControllerButton{
89 	SDL_CONTROLLER_BUTTON_INVALID        = -1,
90 	SDL_CONTROLLER_BUTTON_A              = 0,
91 	SDL_CONTROLLER_BUTTON_B              = 1,
92 	SDL_CONTROLLER_BUTTON_X              = 2,
93 	SDL_CONTROLLER_BUTTON_Y              = 3,
94 	SDL_CONTROLLER_BUTTON_BACK           = 4,
95 	SDL_CONTROLLER_BUTTON_GUIDE          = 5,
96 	SDL_CONTROLLER_BUTTON_START          = 6,
97 	SDL_CONTROLLER_BUTTON_LEFTSTICK      = 7,
98 	SDL_CONTROLLER_BUTTON_RIGHTSTICK     = 8,
99 	SDL_CONTROLLER_BUTTON_LEFTSHOULDER   = 9,
100 	SDL_CONTROLLER_BUTTON_RIGHTSHOULDER  = 10,
101 	SDL_CONTROLLER_BUTTON_DPAD_UP        = 11,
102 	SDL_CONTROLLER_BUTTON_DPAD_DOWN      = 12,
103 	SDL_CONTROLLER_BUTTON_DPAD_LEFT      = 13,
104 	SDL_CONTROLLER_BUTTON_DPAD_RIGHT     = 14,
105 }
106 static if(sdlSupport >= SDLSupport.v2_0_14)
107 enum: SDL_GameControllerButton{
108 	SDL_CONTROLLER_BUTTON_MISC1          = 15,
109 	SDL_CONTROLLER_BUTTON_PADDLE1        = 16,
110 	SDL_CONTROLLER_BUTTON_PADDLE2        = 17,
111 	SDL_CONTROLLER_BUTTON_PADDLE3        = 18,
112 	SDL_CONTROLLER_BUTTON_PADDLE4        = 19,
113 	SDL_CONTROLLER_BUTTON_TOUCHPAD       = 20,
114 	SDL_CONTROLLER_BUTTON_MAX            = 21,
115 }
116 else
117 enum: SDL_GameControllerButton{
118 	SDL_CONTROLLER_BUTTON_MAX            = 15,
119 }
120 
121 static if(sdlSupport >= SDLSupport.v2_0_2){
122 	pragma(inline, true) int SDL_GameControllerAddMappingsFromFile(const(char)* file) nothrow @nogc{
123 		return SDL_GameControllerAddMappingsFromRW(SDL_RWFromFile(file, "rb"), 1);
124 	}
125 }
126 
127 mixin(joinFnBinds((){
128 	FnBind[] ret = [
129 		{q{int}, q{SDL_GameControllerAddMapping}, q{const(char)* mappingString}},
130 		{q{char*}, q{SDL_GameControllerMappingForGUID}, q{SDL_JoystickGUID guid}},
131 		{q{char*}, q{SDL_GameControllerMapping}, q{SDL_GameController* gameController}},
132 		{q{SDL_bool}, q{SDL_IsGameController}, q{int joystickIndex}},
133 		{q{const(char)*}, q{SDL_GameControllerNameForIndex}, q{int joystickIndex}},
134 		{q{SDL_GameController*}, q{SDL_GameControllerOpen}, q{int joystickIndex}},
135 		{q{const(char)*}, q{SDL_GameControllerName}, q{SDL_GameController* gameController}},
136 		{q{SDL_bool}, q{SDL_GameControllerGetAttached}, q{SDL_GameController* gameController}},
137 		{q{SDL_Joystick*}, q{SDL_GameControllerGetJoystick}, q{SDL_GameController* gameController}},
138 		{q{int}, q{SDL_GameControllerEventState}, q{int state}},
139 		{q{void}, q{SDL_GameControllerUpdate}, q{}},
140 		{q{SDL_GameControllerAxis}, q{SDL_GameControllerGetAxisFromString}, q{const(char)* pchString}},
141 		{q{const(char)*}, q{SDL_GameControllerGetStringForAxis}, q{SDL_GameControllerAxis axis}},
142 		{q{SDL_GameControllerButtonBind}, q{SDL_GameControllerGetBindForAxis}, q{SDL_GameController* gameController, SDL_GameControllerAxis axis}},
143 		{q{short}, q{SDL_GameControllerGetAxis}, q{SDL_GameController* gameController, SDL_GameControllerAxis axis}},
144 		{q{SDL_GameControllerButton}, q{SDL_GameControllerGetButtonFromString}, q{const(char*) pchString}},
145 		{q{const(char)*}, q{SDL_GameControllerGetStringForButton}, q{SDL_GameControllerButton button}},
146 		{q{SDL_GameControllerButtonBind}, q{SDL_GameControllerGetBindForButton}, q{SDL_GameController* gameController, SDL_GameControllerButton button}},
147 		{q{ubyte}, q{SDL_GameControllerGetButton}, q{SDL_GameController* gameController, SDL_GameControllerButton button}},
148 		{q{void}, q{SDL_GameControllerClose}, q{SDL_GameController* gameController}},
149 	];
150 	if(sdlSupport >= SDLSupport.v2_0_2){
151 		FnBind[] add = [
152 			{q{int}, q{SDL_GameControllerAddMappingsFromRW}, q{SDL_RWops* rw, int freeRW}},
153 		];
154 		ret ~= add;
155 	}
156 	if(sdlSupport >= SDLSupport.v2_0_4){
157 		FnBind[] add = [
158 			{q{SDL_GameController*}, q{SDL_GameControllerFromInstanceID}, q{SDL_JoystickID joyID}},
159 		];
160 		ret ~= add;
161 	}
162 	if(sdlSupport >= SDLSupport.v2_0_6){
163 		FnBind[] add = [
164 			{q{ushort}, q{SDL_GameControllerGetProduct}, q{SDL_GameController* gameController}},
165 			{q{ushort}, q{SDL_GameControllerGetProductVersion}, q{SDL_GameController* gameController}},
166 			{q{ushort}, q{SDL_GameControllerGetVendor}, q{SDL_GameController* gameController}},
167 			{q{char*}, q{SDL_GameControllerMappingForIndex}, q{int mappingIndex}},
168 			{q{int}, q{SDL_GameControllerNumMappings}, q{}},
169 		];
170 		ret ~= add;
171 	}
172 	if(sdlSupport >= SDLSupport.v2_0_9){
173 		FnBind[] add = [
174 			{q{char*}, q{SDL_GameControllerMappingForDeviceIndex}, q{int joystickIndex}},
175 			{q{int}, q{SDL_GameControllerRumble}, q{SDL_GameController* gameController, ushort lowFrequencyRumble, ushort highFrequencyRumble, uint durationMS}},
176 		];
177 		ret ~= add;
178 	}
179 	if(sdlSupport >= SDLSupport.v2_0_10){
180 		FnBind[] add = [
181 			{q{int}, q{SDL_GameControllerGetPlayerIndex}, q{SDL_GameController* gameController}},
182 		];
183 		ret ~= add;
184 	}
185 	if(sdlSupport >= SDLSupport.v2_0_12){
186 		FnBind[] add = [
187 			{q{SDL_GameControllerType}, q{SDL_GameControllerTypeForIndex}, q{int joystickIndex}},
188 			{q{SDL_GameController*}, q{SDL_GameControllerFromPlayerIndex}, q{int playerIndex}},
189 			{q{SDL_GameControllerType}, q{SDL_GameControllerGetType}, q{SDL_GameController* gameController}},
190 			{q{void}, q{SDL_GameControllerSetPlayerIndex}, q{SDL_GameController* gameController, int playerIndex}},
191 		];
192 		ret ~= add;
193 	}
194 	if(sdlSupport >= SDLSupport.v2_0_14){
195 		FnBind[] add = [
196 			{q{SDL_bool}, q{SDL_GameControllerHasAxis}, q{SDL_GameController* gameController, SDL_GameControllerAxis axis}},
197 			{q{SDL_bool}, q{SDL_GameControllerHasButton}, q{SDL_GameController* gameController, SDL_GameControllerButton button}},
198 			{q{int}, q{SDL_GameControllerGetNumTouchpads}, q{SDL_GameController* gameController}},
199 			{q{int}, q{SDL_GameControllerGetNumTouchpadFingers}, q{SDL_GameController* gameController, int touchpad}},
200 			{q{int}, q{SDL_GameControllerGetTouchpadFinger}, q{SDL_GameController* gameController, int touchpad, int finger, ubyte* state, float* x, float* y, float* pressure}},
201 			{q{SDL_bool}, q{SDL_GameControllerHasSensor}, q{SDL_GameController* gameController, SDL_SensorType type}},
202 			{q{int}, q{SDL_GameControllerSetSensorEnabled}, q{SDL_GameController* gameController, SDL_SensorType type, SDL_bool enabled}},
203 			{q{SDL_bool}, q{SDL_GameControllerIsSensorEnabled}, q{SDL_GameController* gameController, SDL_SensorType type}},
204 			{q{int}, q{SDL_GameControllerGetSensorData}, q{SDL_GameController* gameController, SDL_SensorType type, float* data, int numValues}},
205 			{q{int}, q{SDL_GameControllerRumbleTriggers}, q{SDL_GameController* gameController, ushort leftRumble, ushort rightRumble, uint durationMS}},
206 			{q{SDL_bool}, q{SDL_GameControllerHasLED}, q{SDL_GameController* gameController}},
207 			{q{int}, q{SDL_GameControllerSetLED}, q{SDL_GameController* gameController, ubyte red, ubyte green, ubyte blue}},
208 		];
209 		ret ~= add;
210 	}
211 	if(sdlSupport >= SDLSupport.v2_0_16){
212 		FnBind[] add = [
213 			{q{int}, q{SDL_GameControllerSendEffect}, q{SDL_GameController* gameController, const(void)* data, int size}},
214 			{q{float}, q{SDL_GameControllerGetSensorDataRate}, q{SDL_GameController* gameController, SDL_SensorType type}},
215 		];
216 		ret ~= add;
217 	}
218 	if(sdlSupport >= SDLSupport.v2_0_18){
219 		FnBind[] add = [
220 			{q{SDL_bool}, q{SDL_GameControllerHasRumble}, q{SDL_GameController* gameController}},
221 			{q{SDL_bool}, q{SDL_GameControllerHasRumbleTriggers}, q{SDL_GameController* gameController}},
222 			{q{const(char)*}, q{SDL_GameControllerGetAppleSFSymbolsNameForButton}, q{SDL_GameController* gameController, SDL_GameControllerButton button}},
223 			{q{const(char)*}, q{SDL_GameControllerGetAppleSFSymbolsNameForAxis}, q{SDL_GameController* gameController, SDL_GameControllerAxis axis}},
224 		];
225 		ret ~= add;
226 	}
227 	if(sdlSupport >= SDLSupport.v2_24){
228 		FnBind[] add = [
229 			{q{const(char)*}, q{SDL_GameControllerPathForIndex}, q{int joystickIndex}},
230 			{q{const(char)*}, q{SDL_GameControllerPath}, q{SDL_GameController* gameController}},
231 			{q{ushort}, q{SDL_GameControllerGetFirmwareVersion}, q{SDL_GameController* gameController}},
232 		];
233 		ret ~= add;
234 	}
235 	if(sdlSupport >= SDLSupport.v2_26){
236 		FnBind[] add = [
237 			{q{int}, q{SDL_GameControllerGetSensorDataWithTimestamp}, q{SDL_GameController* gameController, SDL_SensorType type, ulong* timestamp, float* data, int numValues}},
238 		];
239 		ret ~= add;
240 	}
241 	if(sdlSupport >= SDLSupport.v2_30){
242 		FnBind[] add = [
243 			{q{ulong}, q{SDL_GameControllerGetSteamHandle}, q{SDL_GameController* gameController}},
244 		];
245 		ret ~= add;
246 	}
247 	return ret;
248 }()));