1 module unecht.glfw.joysticks; 2 3 import unecht.core.events; 4 5 import derelict.glfw3.glfw3; 6 7 static immutable MAX_AXES = 8; 8 static immutable MAX_BUTTONS = 12; 9 10 /// 11 struct UEJoystickInfo 12 { 13 uint axesCount; 14 uint buttonCount; 15 string name; 16 } 17 18 /// 19 struct UEJoystickState 20 { 21 UEJoystickInfo info; 22 23 bool connected=false; 24 float* glfwAxesPtr; 25 ubyte* glfwButtonPtr; 26 float[MAX_AXES] axesState; 27 ubyte[MAX_BUTTONS] buttonState; 28 } 29 30 /// 31 struct GLFWJoysticks 32 { 33 private UEJoystickState[4] _states; 34 private UEEventsSystem _events; 35 36 void init(UEEventsSystem events) 37 { 38 _events = events; 39 } 40 41 void update() 42 { 43 foreach(int id, ref state; _states) 44 { 45 auto presentNow = glfwJoystickPresent (id); 46 47 if(presentNow && !state.connected) 48 { 49 state.connected = true; 50 connect(id,state); 51 continue; 52 } 53 else if(!presentNow && state.connected) 54 { 55 disconnect(id,state.info.name); 56 state.info.name.length=0; 57 state.connected = false; 58 state.glfwAxesPtr = null; 59 state.glfwButtonPtr = null; 60 state.axesState[] = 0.0f; 61 state.buttonState[] = 0; 62 continue; 63 } 64 65 if(presentNow) 66 { 67 int axesCount; 68 auto axesPtr = glfwGetJoystickAxes (id, &axesCount); 69 auto axesState = axesPtr[0..state.info.axesCount]; 70 71 int buttonCount; 72 auto buttonPtr = glfwGetJoystickButtons (id, &buttonCount); 73 auto buttonState = buttonPtr[0..state.info.buttonCount]; 74 75 if(buttonState != state.buttonState[0..state.info.buttonCount]) 76 { 77 triggerButtonEvent(buttonState,state); 78 state.buttonState[0..state.info.buttonCount] = buttonState; 79 } 80 81 if(axesState != state.axesState[0..state.info.axesCount]) 82 { 83 state.axesState[0..state.info.axesCount] = axesState; 84 triggerAxesEvent(id,axesState,state); 85 } 86 } 87 } 88 } 89 90 void triggerAxesEvent(int id, float[] newState, in UEJoystickState state) 91 { 92 UEEvent ev; 93 ev.eventType = UEEventType.joystickAxes; 94 ev.joystickAxes.axes = newState; 95 ev.joystickAxes.id = id; 96 97 _events.trigger(ev); 98 } 99 100 void triggerButtonEvent(in ubyte[] newState, in UEJoystickState state) 101 { 102 foreach(uint i,button; newState) 103 { 104 if(newState[i] != state.buttonState[i]) 105 { 106 UEEvent ev; 107 ev.eventType = UEEventType.joystickButton; 108 ev.joystickButton.buttonId = i; 109 ev.joystickButton.pressed = button==GLFW_PRESS; 110 111 _events.trigger(ev); 112 } 113 } 114 } 115 116 void connect(int id, ref UEJoystickState state) 117 { 118 state.info.name.length=0; 119 auto cName = glfwGetJoystickName (id); 120 if(cName) 121 { 122 import std.conv; 123 state.info.name = to!string(cName); 124 } 125 126 int axesCount; 127 state.glfwAxesPtr = glfwGetJoystickAxes (id, &axesCount); 128 129 int buttonCount; 130 state.glfwButtonPtr = glfwGetJoystickButtons (id, &buttonCount); 131 132 import std.algorithm:min; 133 state.info.axesCount = min(axesCount,MAX_AXES); 134 state.info.buttonCount = min(buttonCount,MAX_BUTTONS); 135 136 //trigger event 137 { 138 UEEvent ev; 139 ev.eventType = UEEventType.joystickStatus; 140 ev.joystickStatus.connected = true; 141 142 ev.joystickStatus.name = state.info.name; 143 ev.joystickStatus.id = id; 144 ev.joystickStatus.buttonCount = state.info.buttonCount; 145 ev.joystickStatus.axesCount = state.info.axesCount; 146 147 _events.trigger(ev); 148 } 149 } 150 151 void disconnect(int id, string name) 152 { 153 UEEvent ev; 154 ev.eventType = UEEventType.joystickStatus; 155 ev.joystickStatus.connected = false; 156 157 ev.joystickStatus.name = name; 158 ev.joystickStatus.id = id; 159 160 _events.trigger(ev); 161 } 162 }