1 /+
2 +            Copyright 2022 – 2023 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 }
48 
49 alias SDL_GameControllerBindType = uint;
50 enum: SDL_GameControllerBindType{
51 	SDL_CONTROLLER_BINDTYPE_NONE    = 0,
52 	SDL_CONTROLLER_BINDTYPE_BUTTON  = 1,
53 	SDL_CONTROLLER_BINDTYPE_AXIS    = 2,
54 	SDL_CONTROLLER_BINDTYPE_HAT     = 3,
55 }
56 
57 struct SDL_GameControllerButtonBind{
58 	SDL_GameControllerBindType bindType;
59 	union Value_{
60 		int button;
61 		int axis;
62 		struct Hat_{
63 			int hat;
64 			int hat_mask;
65 		}
66 		Hat_ hat;
67 	}
68 	Value_ value;
69 }
70 
71 alias SDL_GameControllerAxis = int;
72 enum: SDL_GameControllerAxis{
73 	SDL_CONTROLLER_AXIS_INVALID = -1,
74 	SDL_CONTROLLER_AXIS_LEFTX,
75 	SDL_CONTROLLER_AXIS_LEFTY,
76 	SDL_CONTROLLER_AXIS_RIGHTX,
77 	SDL_CONTROLLER_AXIS_RIGHTY,
78 	SDL_CONTROLLER_AXIS_TRIGGERLEFT,
79 	SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
80 	SDL_CONTROLLER_AXIS_MAX,
81 }
82 
83 alias SDL_GameControllerButton = int;
84 enum: SDL_GameControllerButton{
85 	SDL_CONTROLLER_BUTTON_INVALID        = -1,
86 	SDL_CONTROLLER_BUTTON_A              = 0,
87 	SDL_CONTROLLER_BUTTON_B              = 1,
88 	SDL_CONTROLLER_BUTTON_X              = 2,
89 	SDL_CONTROLLER_BUTTON_Y              = 3,
90 	SDL_CONTROLLER_BUTTON_BACK           = 4,
91 	SDL_CONTROLLER_BUTTON_GUIDE          = 5,
92 	SDL_CONTROLLER_BUTTON_START          = 6,
93 	SDL_CONTROLLER_BUTTON_LEFTSTICK      = 7,
94 	SDL_CONTROLLER_BUTTON_RIGHTSTICK     = 8,
95 	SDL_CONTROLLER_BUTTON_LEFTSHOULDER   = 9,
96 	SDL_CONTROLLER_BUTTON_RIGHTSHOULDER  = 10,
97 	SDL_CONTROLLER_BUTTON_DPAD_UP        = 12,
98 	SDL_CONTROLLER_BUTTON_DPAD_DOWN      = 13,
99 	SDL_CONTROLLER_BUTTON_DPAD_LEFT      = 14,
100 	SDL_CONTROLLER_BUTTON_DPAD_RIGHT     = 15,
101 }
102 static if(sdlSupport >= SDLSupport.v2_0_14)
103 enum: SDL_GameControllerButton{
104 	SDL_CONTROLLER_BUTTON_MISC1          = 16,
105 	SDL_CONTROLLER_BUTTON_PADDLE1        = 17,
106 	SDL_CONTROLLER_BUTTON_PADDLE2        = 18,
107 	SDL_CONTROLLER_BUTTON_PADDLE3        = 19,
108 	SDL_CONTROLLER_BUTTON_PADDLE4        = 20,
109 	SDL_CONTROLLER_BUTTON_TOUCHPAD       = 21,
110 	SDL_CONTROLLER_BUTTON_MAX            = 22,
111 }
112 else
113 enum: SDL_GameControllerButton{
114 	SDL_CONTROLLER_BUTTON_MAX            = 16,
115 }
116 
117 static if(sdlSupport >= SDLSupport.v2_0_2){
118 	pragma(inline, true) int SDL_GameControllerAddMappingsFromFile(const(char)* file) @nogc nothrow{
119 		return SDL_GameControllerAddMappingsFromRW(SDL_RWFromFile(file, "rb"), 1);
120 	}
121 }
122 
123 mixin(joinFnBinds((){
124 	string[][] ret;
125 	ret ~= makeFnBinds([
126 		[q{int}, q{SDL_GameControllerAddMapping}, q{const(char)* mappingString}],
127 		[q{char*}, q{SDL_GameControllerMappingForGUID}, q{SDL_JoystickGUID guid}],
128 		[q{char*}, q{SDL_GameControllerMapping}, q{SDL_GameController* gamecontroller}],
129 		[q{SDL_bool}, q{SDL_IsGameController}, q{int joystick_index}],
130 		[q{const(char)*}, q{SDL_GameControllerNameForIndex}, q{int joystick_index}],
131 		[q{SDL_GameController*}, q{SDL_GameControllerOpen}, q{int joystick_index}],
132 		[q{const(char)*}, q{SDL_GameControllerName}, q{SDL_GameController* gamecontroller}],
133 		[q{SDL_bool}, q{SDL_GameControllerGetAttached}, q{SDL_GameController* gamecontroller}],
134 		[q{SDL_Joystick*}, q{SDL_GameControllerGetJoystick}, q{SDL_GameController* gamecontroller}],
135 		[q{int}, q{SDL_GameControllerEventState}, q{int state}],
136 		[q{void}, q{SDL_GameControllerUpdate}, q{}],
137 		[q{SDL_GameControllerAxis}, q{SDL_GameControllerGetAxisFromString}, q{const(char)* pchString}],
138 		[q{const(char)*}, q{SDL_GameControllerGetStringForAxis}, q{SDL_GameControllerAxis axis}],
139 		[q{SDL_GameControllerButtonBind}, q{SDL_GameControllerGetBindForAxis}, q{SDL_GameController* gamecontroller, SDL_GameControllerAxis axis}],
140 		[q{short}, q{SDL_GameControllerGetAxis}, q{SDL_GameController* gamecontroller, SDL_GameControllerAxis axis}],
141 		[q{SDL_GameControllerButton}, q{SDL_GameControllerGetButtonFromString}, q{const(char*) pchString}],
142 		[q{const(char)*}, q{SDL_GameControllerGetStringForButton}, q{SDL_GameControllerButton button}],
143 		[q{SDL_GameControllerButtonBind}, q{SDL_GameControllerGetBindForButton}, q{SDL_GameController* gamecontroller, SDL_GameControllerButton button}],
144 		[q{ubyte}, q{SDL_GameControllerGetButton}, q{SDL_GameController* gamecontroller, SDL_GameControllerButton button}],
145 		[q{void}, q{SDL_GameControllerClose}, q{SDL_GameController* gamecontroller}],
146 	]);
147 	static if(sdlSupport >= SDLSupport.v2_0_2){
148 		ret ~= makeFnBinds([
149 			[q{int}, q{SDL_GameControllerAddMappingsFromRW}, q{SDL_RWops* rw, int freerw}],
150 		]);
151 	}
152 	static if(sdlSupport >= SDLSupport.v2_0_4){
153 		ret ~= makeFnBinds([
154 			[q{SDL_GameController*}, q{SDL_GameControllerFromInstanceID}, q{SDL_JoystickID joyid}],
155 		]);
156 	}
157 	static if(sdlSupport >= SDLSupport.v2_0_6){
158 		ret ~= makeFnBinds([
159 			[q{ushort}, q{SDL_GameControllerGetProduct}, q{SDL_GameController* gamecontroller}],
160 			[q{ushort}, q{SDL_GameControllerGetProductVersion}, q{SDL_GameController* gamecontroller}],
161 			[q{ushort}, q{SDL_GameControllerGetVendor}, q{SDL_GameController* gamecontroller}],
162 			[q{char*}, q{SDL_GameControllerMappingForIndex}, q{int mapping_index}],
163 			[q{int}, q{SDL_GameControllerNumMappings}, q{}],
164 		]);
165 	}
166 	static if(sdlSupport >= SDLSupport.v2_0_9){
167 		ret ~= makeFnBinds([
168 			[q{char*}, q{SDL_GameControllerMappingForDeviceIndex}, q{int joystick_index}],
169 			[q{int}, q{SDL_GameControllerRumble}, q{SDL_GameController* gamecontroller, ushort low_frequency_rumble, ushort high_frequency_rumble, uint duration_ms}],
170 		]);
171 	}
172 	static if(sdlSupport >= SDLSupport.v2_0_10){
173 		ret ~= makeFnBinds([
174 			[q{int}, q{SDL_GameControllerGetPlayerIndex}, q{SDL_GameController* gamecontroller}],
175 		]);
176 	}
177 	static if(sdlSupport >= SDLSupport.v2_0_12){
178 		ret ~= makeFnBinds([
179 			[q{SDL_GameControllerType}, q{SDL_GameControllerTypeForIndex}, q{int joystick_index}],
180 			[q{SDL_GameController*}, q{SDL_GameControllerFromPlayerIndex}, q{int player_index}],
181 			[q{SDL_GameControllerType}, q{SDL_GameControllerGetType}, q{SDL_GameController* gamecontroller}],
182 			[q{void}, q{SDL_GameControllerSetPlayerIndex}, q{SDL_GameController* gamecontroller, int player_index}],
183 		]);
184 	}
185 	static if(sdlSupport >= SDLSupport.v2_0_14){
186 		ret ~= makeFnBinds([
187 			[q{SDL_bool}, q{SDL_GameControllerHasAxis}, q{SDL_GameController* gamecontroller, SDL_GameControllerAxis axis}],
188 			[q{SDL_bool}, q{SDL_GameControllerHasButton}, q{SDL_GameController* gamecontroller, SDL_GameControllerButton button}],
189 			[q{int}, q{SDL_GameControllerGetNumTouchpads}, q{SDL_GameController* gamecontroller}],
190 			[q{int}, q{SDL_GameControllerGetNumTouchpadFingers}, q{SDL_GameController* gamecontroller, int touchpad}],
191 			[q{int}, q{SDL_GameControllerGetTouchpadFinger}, q{SDL_GameController* gamecontroller, int touchpad, int finger, ubyte* state, float* x, float* y, float* pressure}],
192 			[q{SDL_bool}, q{SDL_GameControllerHasSensor}, q{SDL_GameController* gamecontroller, SDL_SensorType type}],
193 			[q{int}, q{SDL_GameControllerSetSensorEnabled}, q{SDL_GameController* gamecontroller, SDL_SensorType type, SDL_bool enabled}],
194 			[q{SDL_bool}, q{SDL_GameControllerIsSensorEnabled}, q{SDL_GameController* gamecontroller, SDL_SensorType type}],
195 			[q{int}, q{SDL_GameControllerGetSensorData}, q{SDL_GameController* gamecontroller, SDL_SensorType type, float* data, int num_values}],
196 			[q{int}, q{SDL_GameControllerRumbleTriggers}, q{SDL_GameController* gamecontroller, ushort left_rumble, ushort right_rumble, uint duration_ms}],
197 			[q{SDL_bool}, q{SDL_GameControllerHasLED}, q{SDL_GameController* gamecontroller}],
198 			[q{int}, q{SDL_GameControllerSetLED}, q{SDL_GameController* gamecontroller, ubyte red, ubyte green, ubyte blue}],
199 		]);
200 	}
201 	static if(sdlSupport >= SDLSupport.v2_0_16){
202 		ret ~= makeFnBinds([
203 			[q{int}, q{SDL_GameControllerSendEffect}, q{SDL_GameController* gamecontroller, const(void)* data, int size}],
204 			[q{float}, q{SDL_GameControllerGetSensorDataRate}, q{SDL_GameController* gamecontroller, SDL_SensorType type}],
205 		]);
206 	}
207 	static if(sdlSupport >= SDLSupport.v2_0_18){
208 		ret ~= makeFnBinds([
209 			[q{SDL_bool}, q{SDL_GameControllerHasRumble}, q{SDL_GameController* gamecontroller}],
210 			[q{SDL_bool}, q{SDL_GameControllerHasRumbleTriggers}, q{SDL_GameController* gamecontroller}],
211 			[q{const(char)*}, q{SDL_GameControllerGetAppleSFSymbolsNameForButton}, q{SDL_GameController* gamecontroller, SDL_GameControllerButton button}],
212 			[q{const(char)*}, q{SDL_GameControllerGetAppleSFSymbolsNameForAxis}, q{SDL_GameController* gamecontroller, SDL_GameControllerAxis axis}],
213 		]);
214 	}
215 	static if(sdlSupport >= SDLSupport.v2_24){
216 		ret ~= makeFnBinds([
217 			[q{const(char)*}, q{SDL_GameControllerPathForIndex}, q{int joystick_index}],
218 			[q{const(char)*}, q{SDL_GameControllerPath}, q{SDL_GameController* gamecontroller}],
219 			[q{ushort}, q{SDL_GameControllerGetFirmwareVersion}, q{SDL_GameController* gamecontroller}],
220 		]);
221 	}
222 	static if(sdlSupport >= SDLSupport.v2_26){
223 		ret ~= makeFnBinds([
224 			[q{int}, q{SDL_GameControllerGetSensorDataWithTimestamp}, q{SDL_GameController* gamecontroller, SDL_SensorType type, ulong* timestamp, float* data, int num_values}],
225 		]);
226 	}
227 	return ret;
228 }()));