1 /**
2 Grimoire
3 Copyright (c) 2017 Enalye
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising
7 from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute
11 it freely, subject to the following restrictions:
12 
13 	1. The origin of this software must not be misrepresented;
14 	   you must not claim that you wrote the original software.
15 	   If you use this software in a product, an acknowledgment
16 	   in the product documentation would be appreciated but
17 	   is not required.
18 
19 	2. Altered source versions must be plainly marked as such,
20 	   and must not be misrepresented as being the original software.
21 
22 	3. This notice may not be removed or altered from any source distribution.
23 */
24 
25 module common.controller;
26 
27 import derelict.sdl2.sdl;
28 import core.all;
29 import common.resource;
30 
31 import std..string;
32 import std.file: exists;
33 import std.stdio: writeln, printf;
34 import std.path;
35 
36 private struct Controller {
37     SDL_GameController* sdlController;
38     SDL_Joystick* sdlJoystick;
39     int index, joystickId;
40 }
41 
42 private {
43     Controller[] _controllers;
44 
45     Timer[6] _analogTimers, _analogTimeoutTimers;
46 
47     Vec2f _left = Vec2f.zero, _right = Vec2f.zero;
48 
49     bool _buttonA, _buttonB, _buttonX, _buttonY,
50         _buttonSelect, _buttonMode, _buttonStart,
51         _buttonL1, _buttonR1, _buttonL2, _buttonR2, _buttonL3, _buttonR3,
52         _buttonLeft, _buttonRight, _buttonUp, _buttonDown;
53 
54     bool _singleButtonA, _singleButtonB, _singleButtonX, _singleButtonY,
55         _singleButtonSelect, _singleButtonMode, _singleButtonStart,
56         _singleButtonL1, _singleButtonR1, _singleButtonL2, _singleButtonR2, _singleButtonL3, _singleButtonR3,
57         _singleButtonLeft, _singleButtonRight, _singleButtonUp, _singleButtonDown;
58 }
59 
60 ///Open all the connected controllers
61 void initializeControllers() {
62     const(char)[] dbPath = buildPath(getResourceFolder(), "gamecontrollerdb.txt");
63     if(!exists(dbPath)) {
64         writeln("Could not find \'gamecontrollerdb.txt\'.");
65         return;
66     }
67     if(-1 == SDL_GameControllerAddMappingsFromFile(toStringz(dbPath))) {
68         writeln("Could not open \'gamecontrollerdb.txt\'.");
69         return;
70     }
71     foreach(index; 0.. SDL_NumJoysticks())
72         addController(index);
73     SDL_GameControllerEventState(SDL_ENABLE);
74 }
75 
76 ///Close all the connected controllers
77 void destroyControllers() {
78     foreach(ref controller; _controllers) {
79         SDL_GameControllerClose(controller.sdlController);
80     }
81 }
82 
83 ///Update the state of the controllers
84 void updateControllers(float deltaTime) {
85     foreach(axisIndex; 0.. 4) {
86         _analogTimers[axisIndex].update(deltaTime);
87         _analogTimeoutTimers[axisIndex].update(deltaTime);
88     }
89 }
90 
91 ///Attempt to connect a new controller
92 void addController(int index) {
93     writeln("Detected device at index ", index, ".");
94 
95     auto c = SDL_JoystickNameForIndex(index);
96     auto d = fromStringz(c);
97     writeln("Device name: ", d);
98     
99     if(!SDL_IsGameController(index)) {
100         writeln("The device is not recognised as a game controller.");
101         auto stick = SDL_JoystickOpen(index);
102         auto guid = SDL_JoystickGetGUID(stick);
103         writeln("The device guid is: ");
104         foreach(i; 0.. 16)
105             printf("%02x", guid.data[i]);
106         writeln("");
107         return;
108     }
109     writeln("The device has been detected as a game controller.");
110     foreach(ref controller; _controllers) {
111         if(controller.index == index) {
112             writeln("The controller is already open, aborted.");
113             return;
114         }
115     }
116 
117     auto sdlController = SDL_GameControllerOpen(index);
118     if(!sdlController) {
119         writeln("Could not connect the game controller.");
120         return;
121     }
122 
123     Controller controller;
124     controller.sdlController = sdlController;
125     controller.index = index;
126     controller.sdlJoystick = SDL_GameControllerGetJoystick(controller.sdlController);
127     controller.joystickId = SDL_JoystickInstanceID(controller.sdlJoystick);
128     _controllers ~= controller;
129 
130     writeln("The game controller is now connected.");      
131 }
132 
133 ///Remove a connected controller
134 void removeController(int joystickId) {
135     writeln("Controller disconnected: ", joystickId);
136     
137     int index;
138     bool isControllerPresent;
139     foreach(ref controller; _controllers) {
140         if(controller.joystickId == joystickId) {
141             isControllerPresent = true;
142             break;
143         }
144         index ++;
145     }
146 
147     if(!isControllerPresent)
148         return;
149 
150     SDL_GameControllerClose(_controllers[index].sdlController);
151 
152     //Remove from list
153     if(index + 1 == _controllers.length)
154         _controllers.length --;
155     else if(index == 0)
156         _controllers = _controllers[1.. $];
157     else
158         _controllers = _controllers[0.. index] ~ _controllers[(index + 1) .. $];
159 }
160 
161 ///Called upon remapping
162 void remapController(int joystickId) {
163     writeln("Controller remapped: ", joystickId);
164 }
165 
166 ///Change the value of a controller axis.
167 void setControllerAxis(SDL_GameControllerAxis axis, short value) {
168     auto v = rlerp(-32_768, 32_767, cast(float)value) * 2f - 1f;  
169     switch(axis) {
170     case SDL_CONTROLLER_AXIS_LEFTX:
171         _left.x = v;
172         break;
173     case SDL_CONTROLLER_AXIS_LEFTY:
174         _left.y = v;
175         break;
176     case SDL_CONTROLLER_AXIS_RIGHTX:
177         _right.x = v;
178         break;
179     case SDL_CONTROLLER_AXIS_RIGHTY:
180         _right.y = v;
181         break;
182     case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
183         _buttonL2 = v > .1f;
184         break;
185     case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
186         _buttonR2 = v > .1f;
187         break;
188     default:
189         break;
190     }
191 }
192 
193 ///Handle the timing of the axis
194 private bool updateAnalogTimer(int axisIndex, float x, float y) {
195     if(axisIndex == -1)
196         return false;
197 
198     enum deadzone = .5f;
199     if((x < deadzone && x > -deadzone) && (y < deadzone && y > -deadzone))  {
200         _analogTimeoutTimers[axisIndex].stop();
201         return false;
202     }
203     else {
204         if(_analogTimers[axisIndex].isRunning)
205             return false;
206         _analogTimers[axisIndex].start(_analogTimeoutTimers[axisIndex].isRunning ? .15f : .35f);
207         _analogTimeoutTimers[axisIndex].start(5f);
208     }
209     return true;
210 }
211 
212 ///Change the value of a controller button.
213 void setControllerButton(SDL_GameControllerButton button, bool state) {
214     switch(button) {
215     case SDL_CONTROLLER_BUTTON_A:
216         _buttonA = state;
217         _singleButtonA = state;
218         break;
219     case SDL_CONTROLLER_BUTTON_B:
220         _buttonB = state;
221         _singleButtonB = state;
222         break;
223     case SDL_CONTROLLER_BUTTON_X:
224         _buttonX = state;
225         _singleButtonX = state;
226         break;
227     case SDL_CONTROLLER_BUTTON_Y:
228         _buttonY = state;
229         _singleButtonY = state;
230         break;
231     case SDL_CONTROLLER_BUTTON_BACK:
232         _buttonSelect = state;
233         _singleButtonSelect = state;
234         break;
235     case SDL_CONTROLLER_BUTTON_GUIDE:
236         _buttonMode = state;
237         _singleButtonMode = state;
238         break;
239     case SDL_CONTROLLER_BUTTON_START:
240         _buttonStart = state;
241         _singleButtonStart = state;
242         break;
243     case SDL_CONTROLLER_BUTTON_LEFTSTICK:
244         _buttonL3 = state;
245         _singleButtonL3 = state;
246         break;
247     case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
248         _buttonR3 = state;
249         _singleButtonR3 = state;
250         break;
251     case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
252         _buttonL1 = state;
253         _singleButtonL1 = state;
254         break;
255     case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
256         _buttonR1 = state;
257         _singleButtonR1 = state;
258         break;
259     case SDL_CONTROLLER_BUTTON_DPAD_UP:
260         _buttonUp = state;
261         _singleButtonUp = state;
262         break;
263     case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
264         _buttonDown = state;
265         _singleButtonDown = state;
266         break;
267     case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
268         _buttonLeft = state;
269         _singleButtonLeft = state;
270         break;
271     case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
272         _buttonRight = state;
273         _singleButtonRight = state;
274         break;
275     default:
276         break;
277     }
278 }
279 
280 @property {
281     ///Left analog stick
282     Vec2f inputLAnalog() {
283         return _left;
284     }
285 
286     ///Right analog stick
287     Vec2f inputRAnalog() {
288         return _right;
289     }
290 
291     //Continuous buttons
292 
293     ///Is the A button pressed.
294     bool inputA() {
295         _singleButtonA = false;
296         return _buttonA;
297     }
298 
299     ///Is the B button pressed.
300     bool inputB() {
301         _singleButtonB = false;
302         return _buttonB;
303     }
304 
305     ///Is the X button pressed.
306     bool inputX() {
307         _singleButtonX = false;
308         return _buttonX;
309     }
310 
311     ///Is the Y button pressed.
312     bool inputY() {
313         _singleButtonY = false;
314         return _buttonY;
315     }
316 
317     ///Is the Select button pressed.
318     bool inputSelect() {
319         _singleButtonSelect = false;
320         return _buttonSelect;
321     }
322 
323     ///Is the Mode button pressed.
324     bool inputMode() {
325         _singleButtonMode = false;
326         return _buttonMode;
327     }
328 
329     ///Is the Start button pressed.
330     bool inputStart() {
331         _singleButtonStart = false;
332         return _buttonStart;
333     }
334 
335     ///Is the L1 button pressed.
336     bool inputL1() {
337         _singleButtonL1 = false;
338         return _buttonL1;
339     }
340 
341     ///Is the R1 button pressed.
342     bool inputR1() {
343         _singleButtonR1 = false;
344         return _buttonR1;
345     }
346 
347     ///Is the L2 button pressed.
348     bool inputL2() {
349         _singleButtonL2 = false;
350         return _buttonL2;
351     }
352 
353     ///Is the R2 button pressed.
354     bool inputR2() {
355         _singleButtonR2 = false;
356         return _buttonR2;
357     }
358 
359     ///Is the L3 button pressed.
360     bool inputL3() {
361         _singleButtonL3 = false;
362         return _buttonL3;
363     }
364 
365     ///Is the R3 button pressed.
366     bool inputR3() {
367         _singleButtonR3 = false;
368         return _buttonR3;
369     }
370 
371     ///Is the Left button pressed.
372     bool inputLeft() {
373         _singleButtonLeft = false;
374         return _buttonLeft;
375     }
376 
377     ///Is the Right button pressed.
378     bool inputRight() {
379         _singleButtonRight = false;
380         return _buttonRight;
381     }
382 
383     ///Is the Up button pressed.
384     bool inputUp() {
385         _singleButtonUp = false;
386         return _buttonUp;
387     }
388 
389     ///Is the Down button pressed.
390     bool inputDown() {
391         _singleButtonDown = false;
392         return _buttonDown;
393     }
394 
395     //Single action buttons
396 
397     ///Is the A button pressed.
398     ///Returns true only if the button was not already tested.
399     bool inputSingleA() {
400         auto state = _singleButtonA;
401         _singleButtonA = false;
402         return state;
403     }
404 
405     ///Is the B button pressed.
406     ///Returns true only if the button was not already tested.
407     bool inputSingleB() {
408         auto state = _singleButtonB;
409         _singleButtonB = false;
410         return state;
411     }
412 
413     ///Is the X button pressed.
414     ///Returns true only if the button was not already tested.
415     bool inputSingleX() {
416         auto state = _singleButtonX;
417         _singleButtonX = false;
418         return state;
419     }
420 
421     ///Is the Y button pressed.
422     ///Returns true only if the button was not already tested.
423     bool inputSingleY() {
424         auto state = _singleButtonY;
425         _singleButtonY = false;
426         return state;
427     }
428 
429     ///Is the Select button pressed.
430     ///Returns true only if the button was not already tested.
431     bool inputSingleSelect() {
432         auto state = _singleButtonSelect;
433         _singleButtonSelect = false;
434         return state;
435     }
436 
437     ///Is the Mode button pressed.
438     ///Returns true only if the button was not already tested.
439     bool inputSingleMode() {
440         auto state = _singleButtonMode;
441         _singleButtonMode = false;
442         return state;
443     }
444 
445     ///Is the Start button pressed.
446     ///Returns true only if the button was not already tested.
447     bool inputSingleStart() {
448         auto state = _singleButtonStart;
449         _singleButtonStart = false;
450         return state;
451     }
452 
453     ///Is the L1 button pressed.
454     ///Returns true only if the button was not already tested.
455     bool inputSingleL1() {
456         auto state = _singleButtonL1;
457         _singleButtonL1 = false;
458         return state;
459     }
460 
461     ///Is the R1 button pressed.
462     ///Returns true only if the button was not already tested.
463     bool inputSingleR1() {
464         auto state = _singleButtonR1;
465         _singleButtonR1 = false;
466         return state;
467     }
468 
469     ///Is the L2 button pressed.
470     ///Returns true only if the button was not already tested.
471     bool inputSingleL2() {
472         auto state = _singleButtonL2;
473         _singleButtonL2 = false;
474         return state;
475     }
476 
477     ///Is the R2 button pressed.
478     ///Returns true only if the button was not already tested.
479     bool inputSingleR2() {
480         auto state = _singleButtonR2;
481         _singleButtonR2 = false;
482         return state;
483     }
484 
485     ///Is the L3 button pressed.
486     ///Returns true only if the button was not already tested.
487     bool inputSingleL3() {
488         auto state = _singleButtonL3;
489         _singleButtonL3 = false;
490         return state;
491     }
492 
493     ///Is the R3 button pressed.
494     ///Returns true only if the button was not already tested.
495     bool inputSingleR3() {
496         auto state = _singleButtonR3;
497         _singleButtonR3 = false;
498         return state;
499     }
500 
501     ///Is the Left button pressed.
502     ///Returns true only if the button was not already tested.
503     bool inputSingleLeft() {
504         auto state = _singleButtonRight;
505         _singleButtonRight = false;
506         return state;
507     }
508 
509     ///Is the Right button pressed.
510     ///Returns true only if the button was not already tested.
511     bool inputSingleRight() {
512         auto state = _singleButtonRight;
513         _singleButtonRight = false;
514         return state;
515     }
516 
517     ///Is the Up button pressed.
518     ///Returns true only if the button was not already tested.
519     bool inputSingleUp() {
520         auto state = _singleButtonUp;
521         _singleButtonUp = false;
522         return state;
523     }
524 
525     ///Is the Down button pressed.
526     ///Returns true only if the button was not already tested.
527     bool inputSingleDown() {
528         auto state = _singleButtonDown;
529         _singleButtonDown = false;
530         return state;
531     }
532 
533     ///Returns the left stick x-axis as a button.
534     bool inputSingleLeftX() {
535         return updateAnalogTimer(0, _left.x, 0f);
536     }
537 
538     ///Returns the left stick y-axis as a button.
539     bool inputSingleLeftY() {
540         return updateAnalogTimer(1, 0f, _left.y);        
541     }
542 
543     ///Returns the left stick x and y axis as a button.
544     bool inputSingleLeftXY() {
545         return updateAnalogTimer(2, _left.x, _left.y);        
546     }
547 
548     ///Returns the right stick x-axis as a button.
549     bool inputSingleRightX() {
550         return updateAnalogTimer(3, _right.x, 0f);
551     }
552 
553     ///Returns the right stick y-axis as a button.
554     bool inputSingleRightY() {
555         return updateAnalogTimer(4, 0f, _right.y);        
556     }
557 
558     ///Returns the right stick x and y axis as a button.
559     bool inputSingleRightXY() {
560         return updateAnalogTimer(5, _right.x, _right.y);        
561     }
562 }