1 module sily.sdl.input; 2 3 import std.traits; 4 import std.algorithm; 5 import std.range; 6 import std.conv; 7 8 import bindbc.sdl; 9 10 // FIXME: window 11 // import terramatter.render.window; 12 import sily.vector; 13 14 static class Input { 15 private static KeyState[KeyCode] s_keyStates; 16 private static KeyState[MouseCode] s_mbStates; 17 private static KeyCode[SDL_Scancode] s_keyConv; 18 private static MouseCode[ubyte] s_mbConv; 19 20 private static Vector2i s_mouseMotion; 21 private static Vector2i s_mousePosition; 22 23 private static KeyCode s_lastKey; 24 25 public static void update() { 26 SDL_Event e; 27 28 foreach (skey; s_keyStates.keys) { 29 if (s_keyStates[skey] == KeyState.justPressed) s_keyStates[skey] = KeyState.pressed; 30 if (s_keyStates[skey] == KeyState.justReleased) s_keyStates[skey] = KeyState.released; 31 } 32 33 foreach (skey; s_mbStates.keys) { 34 if (s_mbStates[skey] == KeyState.justPressed) s_mbStates[skey] = KeyState.pressed; 35 if (s_mbStates[skey] == KeyState.justReleased) s_mbStates[skey] = KeyState.released; 36 } 37 38 s_mouseMotion.x = 0; 39 s_mouseMotion.y = 0; 40 41 while (SDL_PollEvent(&e)) { 42 switch (e.type) { 43 case SDL_EventType.SDL_KEYDOWN: 44 KeyCode key = getKeyCodeSDL(e.key.keysym.scancode); 45 // TODO fire up key repeat event 46 s_lastKey = key; 47 if (s_keyStates[key] == KeyState.pressed) break; 48 s_keyStates[key] = KeyState.justPressed; 49 break; 50 case SDL_EventType.SDL_KEYUP: 51 KeyCode key = getKeyCodeSDL(e.key.keysym.scancode); 52 s_keyStates[key] = KeyState.justReleased; 53 break; 54 case SDL_EventType.SDL_MOUSEBUTTONDOWN: 55 MouseCode key = getMouseCodeSDL(e.button.button); 56 s_mbStates[key] = KeyState.justPressed; 57 // TODO emit event on e.button.clicks == 2 58 break; 59 case SDL_EventType.SDL_MOUSEBUTTONUP: 60 MouseCode key = getMouseCodeSDL(e.button.button); 61 s_mbStates[key] = KeyState.justReleased; 62 break; 63 case SDL_EventType.SDL_MOUSEMOTION: 64 s_mouseMotion.x = e.motion.xrel; 65 s_mouseMotion.y = e.motion.yrel; 66 s_mousePosition.x = e.motion.x; 67 s_mousePosition.y = e.motion.y; 68 break; 69 case SDL_EventType.SDL_MOUSEWHEEL: 70 if(e.wheel.y> 0) { // scroll up 71 // TODO scroll up 72 } else 73 if(e.wheel.y < 0) { // scroll down 74 // TODO scroll down 75 } 76 77 if(e.wheel.x > 0) { // scroll right 78 // TODO scroll right 79 } else 80 if(e.wheel.x < 0) { // scroll left 81 // TODO scroll left 82 } 83 break; 84 // Close application button 85 case SDL_EventType.SDL_QUIT: 86 // Window.setRequestedClose(true); 87 break; 88 default: 89 // 90 } 91 } 92 } 93 94 public static Vector2i getMouseRelative() { 95 return s_mouseMotion; 96 } 97 98 public static Vector2i getMousePosition() { 99 return s_mousePosition; 100 } 101 102 public static void setRelativeMouseMode(bool enabled) { 103 SDL_SetRelativeMouseMode(enabled.to!SDL_bool); 104 } 105 106 public static bool getRelativeMouseMode() { 107 return SDL_GetRelativeMouseMode().to!bool; 108 } 109 110 public static void setMousePosition(int[2] pos ...) { 111 // SDL_WarpMouseInWindow(Window.getWindow, pos[0], pos[1]); 112 } 113 114 public static void setMousePositionScreen(int[2] pos ...) { 115 SDL_WarpMouseGlobal(pos[0], pos[1]); 116 } 117 118 public static bool isKeyJustPressed(KeyCode p_key){ 119 return s_keyStates[p_key] == KeyState.justPressed; 120 } 121 122 public static bool isKeyPressed(KeyCode p_key){ 123 return s_keyStates[p_key] == KeyState.justPressed || 124 s_keyStates[p_key] == KeyState.pressed; 125 } 126 127 public static bool isKeyJustReleased(KeyCode p_key){ 128 return s_keyStates[p_key] == KeyState.justReleased; 129 } 130 131 public static bool isKeyReleased(KeyCode p_key){ 132 return s_keyStates[p_key] == KeyState.justReleased || 133 s_keyStates[p_key] == KeyState.released; 134 } 135 136 public static bool isMouseJustPressed(MouseCode p_key){ 137 return s_mbStates[p_key] == KeyState.justPressed; 138 } 139 140 public static bool isMousePressed(MouseCode p_key){ 141 return s_mbStates[p_key] == KeyState.justPressed || 142 s_mbStates[p_key] == KeyState.pressed; 143 } 144 145 public static bool isMouseJustReleased(MouseCode p_key){ 146 return s_mbStates[p_key] == KeyState.justReleased; 147 } 148 149 public static bool isMouseReleased(MouseCode p_key){ 150 return s_mbStates[p_key] == KeyState.justReleased || 151 s_mbStates[p_key] == KeyState.released; 152 } 153 154 static this() { 155 foreach (skey; EnumMembers!KeyCode) { 156 s_keyStates[skey] = KeyState.released; 157 } 158 159 foreach (skey; EnumMembers!KeyCode) { 160 s_keyConv[skey.to!SDL_Scancode] = skey; 161 } 162 163 foreach (skey; EnumMembers!MouseCode) { 164 s_mbConv[skey.to!ubyte] = skey; 165 } 166 167 s_mouseMotion = Vector2i(0, 0); 168 s_mousePosition = Vector2i(0, 0); 169 } 170 171 public static int keyCodeLength() { 172 return EnumMembers!KeyCode.length; 173 } 174 175 private static KeyCode getKeyCodeSDL(SDL_Scancode p_code) { 176 return s_keyConv[p_code]; 177 } 178 179 private static MouseCode getMouseCodeSDL(ubyte p_code) { 180 return s_mbConv[p_code]; 181 } 182 183 static enum MouseCode { 184 mbLeft = SDL_BUTTON_LEFT, 185 mbRight = SDL_BUTTON_RIGHT, 186 mbMiddle = SDL_BUTTON_MIDDLE, 187 mbX1 = SDL_BUTTON_X1, 188 mbX2 = SDL_BUTTON_X2, 189 } 190 191 static enum KeyState { 192 justPressed, 193 pressed, 194 justReleased, 195 released 196 } 197 198 static enum KeyCode { 199 // LETTERS 200 keyA = SDL_Scancode.SDL_SCANCODE_A, 201 keyB = SDL_Scancode.SDL_SCANCODE_B, 202 keyC = SDL_Scancode.SDL_SCANCODE_C, 203 keyD = SDL_Scancode.SDL_SCANCODE_D, 204 keyE = SDL_Scancode.SDL_SCANCODE_E, 205 keyF = SDL_Scancode.SDL_SCANCODE_F, 206 keyG = SDL_Scancode.SDL_SCANCODE_G, 207 keyH = SDL_Scancode.SDL_SCANCODE_H, 208 keyI = SDL_Scancode.SDL_SCANCODE_I, 209 keyJ = SDL_Scancode.SDL_SCANCODE_J, 210 keyK = SDL_Scancode.SDL_SCANCODE_K, 211 keyL = SDL_Scancode.SDL_SCANCODE_L, 212 keyM = SDL_Scancode.SDL_SCANCODE_M, 213 keyN = SDL_Scancode.SDL_SCANCODE_N, 214 keyO = SDL_Scancode.SDL_SCANCODE_O, 215 keyP = SDL_Scancode.SDL_SCANCODE_P, 216 keyQ = SDL_Scancode.SDL_SCANCODE_Q, 217 keyR = SDL_Scancode.SDL_SCANCODE_R, 218 keyS = SDL_Scancode.SDL_SCANCODE_S, 219 keyT = SDL_Scancode.SDL_SCANCODE_T, 220 keyU = SDL_Scancode.SDL_SCANCODE_U, 221 keyV = SDL_Scancode.SDL_SCANCODE_V, 222 keyW = SDL_Scancode.SDL_SCANCODE_W, 223 keyX = SDL_Scancode.SDL_SCANCODE_X, 224 keyY = SDL_Scancode.SDL_SCANCODE_Y, 225 keyZ = SDL_Scancode.SDL_SCANCODE_Z, 226 227 // NUMBERS 228 key0 = SDL_Scancode.SDL_SCANCODE_0, 229 key1 = SDL_Scancode.SDL_SCANCODE_1, 230 key2 = SDL_Scancode.SDL_SCANCODE_2, 231 key3 = SDL_Scancode.SDL_SCANCODE_3, 232 key4 = SDL_Scancode.SDL_SCANCODE_4, 233 key5 = SDL_Scancode.SDL_SCANCODE_5, 234 key6 = SDL_Scancode.SDL_SCANCODE_6, 235 key7 = SDL_Scancode.SDL_SCANCODE_7, 236 key8 = SDL_Scancode.SDL_SCANCODE_8, 237 key9 = SDL_Scancode.SDL_SCANCODE_9, 238 239 // FUNCTION KEYS 240 keyF1 = SDL_Scancode.SDL_SCANCODE_F1, 241 keyF2 = SDL_Scancode.SDL_SCANCODE_F2, 242 keyF3 = SDL_Scancode.SDL_SCANCODE_F3, 243 keyF4 = SDL_Scancode.SDL_SCANCODE_F4, 244 keyF5 = SDL_Scancode.SDL_SCANCODE_F5, 245 keyF6 = SDL_Scancode.SDL_SCANCODE_F6, 246 keyF7 = SDL_Scancode.SDL_SCANCODE_F7, 247 keyF8 = SDL_Scancode.SDL_SCANCODE_F8, 248 keyF9 = SDL_Scancode.SDL_SCANCODE_F9, 249 keyF10 = SDL_Scancode.SDL_SCANCODE_F10, 250 keyF11 = SDL_Scancode.SDL_SCANCODE_F11, 251 keyF12 = SDL_Scancode.SDL_SCANCODE_F12, 252 keyF13 = SDL_Scancode.SDL_SCANCODE_F13, 253 keyF14 = SDL_Scancode.SDL_SCANCODE_F14, 254 keyF15 = SDL_Scancode.SDL_SCANCODE_F15, 255 keyF16 = SDL_Scancode.SDL_SCANCODE_F16, 256 keyF17 = SDL_Scancode.SDL_SCANCODE_F17, 257 keyF18 = SDL_Scancode.SDL_SCANCODE_F18, 258 keyF19 = SDL_Scancode.SDL_SCANCODE_F19, 259 keyF20 = SDL_Scancode.SDL_SCANCODE_F20, 260 keyF21 = SDL_Scancode.SDL_SCANCODE_F21, 261 keyF22 = SDL_Scancode.SDL_SCANCODE_F22, 262 keyF23 = SDL_Scancode.SDL_SCANCODE_F23, 263 keyF24 = SDL_Scancode.SDL_SCANCODE_F24, 264 265 // NUMBER ROW (1ST ROW) 266 keyESC = SDL_Scancode.SDL_SCANCODE_ESCAPE, 267 keyGrave = SDL_Scancode.SDL_SCANCODE_GRAVE, 268 keyMinus = SDL_Scancode.SDL_SCANCODE_MINUS, 269 keyEquals = SDL_Scancode.SDL_SCANCODE_EQUALS, 270 keyBackspace = SDL_Scancode.SDL_SCANCODE_BACKSPACE, 271 272 // 2ND ROW 273 keyTab = SDL_Scancode.SDL_SCANCODE_TAB, 274 keyLeftBracket = SDL_Scancode.SDL_SCANCODE_LEFTBRACKET, 275 keyRightBracket = SDL_Scancode.SDL_SCANCODE_RIGHTBRACKET, 276 keyBackslash = SDL_Scancode.SDL_SCANCODE_BACKSLASH, 277 278 // 3RD ROW 279 keyCapsLock = SDL_Scancode.SDL_SCANCODE_CAPSLOCK, 280 keySemicolon = SDL_Scancode.SDL_SCANCODE_SEMICOLON, 281 keyApostrophe = SDL_Scancode.SDL_SCANCODE_APOSTROPHE, 282 keyReturn = SDL_Scancode.SDL_SCANCODE_RETURN, 283 284 // 4RTH ROW 285 keyLeftShift = SDL_Scancode.SDL_SCANCODE_LSHIFT, 286 keyComma = SDL_Scancode.SDL_SCANCODE_COMMA, 287 keyPeriod = SDL_Scancode.SDL_SCANCODE_PERIOD, 288 keySlash = SDL_Scancode.SDL_SCANCODE_SLASH, 289 keyRightShift = SDL_Scancode.SDL_SCANCODE_RSHIFT, 290 291 // BOTTOM ROW 292 keyLeftControl = SDL_Scancode.SDL_SCANCODE_LCTRL, 293 keyApplication = SDL_Scancode.SDL_SCANCODE_APPLICATION, 294 keyLeftAlt = SDL_Scancode.SDL_SCANCODE_LALT, 295 keySpace = SDL_Scancode.SDL_SCANCODE_SPACE, 296 keyRightAlt = SDL_Scancode.SDL_SCANCODE_RALT, 297 keyLeftGUI = SDL_Scancode.SDL_SCANCODE_LGUI, 298 keyRightGUI = SDL_Scancode.SDL_SCANCODE_RGUI, 299 keyRightControl = SDL_Scancode.SDL_SCANCODE_RCTRL, 300 301 // KEYPAD 302 keyLeft = SDL_Scancode.SDL_SCANCODE_LEFT, 303 keyRight = SDL_Scancode.SDL_SCANCODE_RIGHT, 304 keyUp = SDL_Scancode.SDL_SCANCODE_UP, 305 keyDown = SDL_Scancode.SDL_SCANCODE_DOWN, 306 307 // HOME 308 keyHome = SDL_Scancode.SDL_SCANCODE_HOME, 309 keyEnd = SDL_Scancode.SDL_SCANCODE_END, 310 keyPageUp = SDL_Scancode.SDL_SCANCODE_PAGEUP, 311 keyPageDown = SDL_Scancode.SDL_SCANCODE_PAGEDOWN, 312 keyInsert = SDL_Scancode.SDL_SCANCODE_INSERT, 313 keyDelete = SDL_Scancode.SDL_SCANCODE_DELETE, 314 315 // SCROLL LOCK 316 keyScrollLock = SDL_Scancode.SDL_SCANCODE_SCROLLLOCK, 317 keyPrintScreen = SDL_Scancode.SDL_SCANCODE_PRINTSCREEN, 318 keyPause = SDL_Scancode.SDL_SCANCODE_PAUSE 319 320 // TODO NUMPAD 321 } 322 } 323 324 class InputEvent { 325 326 }