1 module prova.input.controller; 2 3 import derelict.sdl2.sdl, 4 prova.math; 5 6 /// 7 enum ThumbStick { LEFT, RIGHT } 8 9 /// 10 enum ControllerButton { 11 A, B, X, Y, BACK, GUIDE, START, 12 LEFT_STICK, RIGHT_STICK, BUMPER_LEFT, BUMPER_RIGHT, 13 DPAD_UP, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, 14 // simulated buttons 15 TRIGGER_LEFT, TRIGGER_RIGHT 16 } 17 18 /// 19 class Controller 20 { 21 /// 22 float deadzone = .15; 23 private SDL_GameController* handle; 24 private int[18] oldButtonState; 25 private int[18] buttonState; 26 private int _id; 27 28 package this(int index) 29 { 30 _id = index; 31 handle = SDL_GameControllerOpen(index); 32 33 foreach(i; 0 .. 17) { 34 oldButtonState[i] = false; 35 buttonState[i] = false; 36 } 37 } 38 39 /// 40 @property int id() 41 { 42 return _id; 43 } 44 45 /// 46 bool isConnected() 47 { 48 return cast(bool) SDL_GameControllerGetAttached(handle); 49 } 50 51 package void update() 52 { 53 foreach(i; 0 .. 17) { 54 oldButtonState[i] = buttonState[i]; 55 buttonState[i] = getButtonState(cast(ControllerButton) i); 56 } 57 } 58 59 private bool getButtonState(ControllerButton button) 60 { 61 if(button == ControllerButton.TRIGGER_LEFT || button == ControllerButton.TRIGGER_RIGHT) 62 return getTrigger(button) > .3; 63 return cast(bool) SDL_GameControllerGetButton(handle, cast(SDL_GameControllerButton) button); 64 } 65 66 /// 67 bool isButtonDown(ControllerButton button) 68 { 69 return cast(bool) buttonState[cast(int) button]; 70 } 71 72 /// 73 bool isButtonUp(ControllerButton button) 74 { 75 return !buttonState[cast(int) button]; 76 } 77 78 /// 79 bool buttonJustPressed(ControllerButton button) 80 { 81 return buttonState[cast(int) button] && !oldButtonState[cast(int) button]; 82 } 83 84 /// 85 Vector2 getStick(ThumbStick stick) 86 { 87 int xAxis = SDL_CONTROLLER_AXIS_LEFTX; 88 89 if(stick == ThumbStick.RIGHT) 90 xAxis = SDL_CONTROLLER_AXIS_RIGHTX; 91 92 Vector2 displacement = Vector2(getAxis(xAxis), -getAxis(xAxis + 1)); 93 94 if(displacement.getMagnitude() <= deadzone) 95 return Vector2(); 96 else 97 return displacement; 98 } 99 100 /// 101 float getTrigger(ControllerButton button) 102 { 103 if(button == ControllerButton.TRIGGER_LEFT) 104 return getAxis(SDL_CONTROLLER_AXIS_TRIGGERLEFT); 105 if(button == ControllerButton.TRIGGER_RIGHT) 106 return getAxis(SDL_CONTROLLER_AXIS_TRIGGERRIGHT); 107 108 throw new Exception("Specified button is not a trigger."); 109 } 110 111 private float getAxis(int axis) 112 { 113 return SDL_GameControllerGetAxis(handle, cast(SDL_GameControllerAxis) axis) / cast(float) 32767; 114 } 115 116 ~this() 117 { 118 SDL_GameControllerClose(handle); 119 } 120 }