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