1 /* 2 Copyright © 2020, Luna Nielsen 3 Distributed under the 2-Clause BSD License, see LICENSE file. 4 5 Authors: Luna Nielsen 6 */ 7 module engine.input.keyboard; 8 import engine.input; 9 import bindbc.glfw; 10 import events; 11 12 /** 13 Keys 14 */ 15 enum Key { 16 KeyUnknown = GLFW_KEY_UNKNOWN, 17 KeySpace = GLFW_KEY_SPACE, 18 KeyApostrophe = GLFW_KEY_APOSTROPHE, 19 KeyComma = GLFW_KEY_COMMA, 20 KeyMinus = GLFW_KEY_MINUS, 21 KeyPeriod = GLFW_KEY_PERIOD, 22 KeySlash = GLFW_KEY_SLASH, 23 Key0 = GLFW_KEY_0, 24 Key1 = GLFW_KEY_1, 25 Key2 = GLFW_KEY_2, 26 Key3 = GLFW_KEY_3, 27 Key4 = GLFW_KEY_4, 28 Key5 = GLFW_KEY_5, 29 Key6 = GLFW_KEY_6, 30 Key7 = GLFW_KEY_7, 31 Key8 = GLFW_KEY_8, 32 Key9 = GLFW_KEY_9, 33 KeySemicolon = GLFW_KEY_SEMICOLON, 34 KeyEqual = GLFW_KEY_EQUAL, 35 KeyA = GLFW_KEY_A, 36 KeyB = GLFW_KEY_B, 37 KeyC = GLFW_KEY_C, 38 KeyD = GLFW_KEY_D, 39 KeyE = GLFW_KEY_E, 40 KeyF = GLFW_KEY_F, 41 KeyG = GLFW_KEY_G, 42 KeyH = GLFW_KEY_H, 43 KeyI = GLFW_KEY_I, 44 KeyJ = GLFW_KEY_J, 45 KeyK = GLFW_KEY_K, 46 KeyL = GLFW_KEY_L, 47 KeyM = GLFW_KEY_M, 48 KeyN = GLFW_KEY_N, 49 KeyO = GLFW_KEY_O, 50 KeyP = GLFW_KEY_P, 51 KeyQ = GLFW_KEY_Q, 52 KeyR = GLFW_KEY_R, 53 KeyS = GLFW_KEY_S, 54 KeyT = GLFW_KEY_T, 55 KeyU = GLFW_KEY_U, 56 KeyV = GLFW_KEY_V, 57 KeyW = GLFW_KEY_W, 58 KeyX = GLFW_KEY_X, 59 KeyY = GLFW_KEY_Y, 60 KeyZ = GLFW_KEY_Z, 61 KeyBracket = GLFW_KEY_LEFT_BRACKET, 62 KeyBackslash = GLFW_KEY_BACKSLASH, 63 KeyRightBracket = GLFW_KEY_RIGHT_BRACKET, 64 KeyAccent = GLFW_KEY_GRAVE_ACCENT, 65 KeyWorld1 = GLFW_KEY_WORLD_1, 66 KeyWorld2 = GLFW_KEY_WORLD_2, 67 68 KeyEscape = GLFW_KEY_ESCAPE, 69 KeyEnter = GLFW_KEY_ENTER, 70 KeyTab = GLFW_KEY_TAB, 71 KeyBackspace = GLFW_KEY_BACKSPACE, 72 KeyInsert = GLFW_KEY_INSERT, 73 KeyDelete = GLFW_KEY_DELETE, 74 KeyRight = GLFW_KEY_RIGHT, 75 KeyLeft = GLFW_KEY_LEFT, 76 KeyDown = GLFW_KEY_DOWN, 77 KeyUp = GLFW_KEY_UP, 78 KeyPageUp = GLFW_KEY_PAGE_UP, 79 KeyPageDown = GLFW_KEY_PAGE_DOWN, 80 KeyHome = GLFW_KEY_HOME, 81 KeyEnd = GLFW_KEY_END, 82 KeyCapsLock = GLFW_KEY_CAPS_LOCK, 83 KeyScrollLock = GLFW_KEY_SCROLL_LOCK, 84 KeyNumLock = GLFW_KEY_NUM_LOCK, 85 KeyPrintScreen = GLFW_KEY_PRINT_SCREEN, 86 KeyPause = GLFW_KEY_PAUSE, 87 KeyF1 = GLFW_KEY_F1, 88 KeyF2 = GLFW_KEY_F2, 89 KeyF3 = GLFW_KEY_F3, 90 KeyF4 = GLFW_KEY_F4, 91 KeyF5 = GLFW_KEY_F5, 92 KeyF6 = GLFW_KEY_F6, 93 KeyF7 = GLFW_KEY_F7, 94 KeyF8 = GLFW_KEY_F8, 95 KeyF9 = GLFW_KEY_F9, 96 KeyF10 = GLFW_KEY_F10, 97 KeyF11 = GLFW_KEY_F11, 98 KeyF12 = GLFW_KEY_F12, 99 KeyF13 = GLFW_KEY_F13, 100 KeyF14 = GLFW_KEY_F14, 101 KeyF15 = GLFW_KEY_F15, 102 KeyF16 = GLFW_KEY_F16, 103 KeyF17 = GLFW_KEY_F17, 104 KeyF18 = GLFW_KEY_F18, 105 KeyF19 = GLFW_KEY_F19, 106 KeyF20 = GLFW_KEY_F20, 107 KeyF21 = GLFW_KEY_F21, 108 KeyF22 = GLFW_KEY_F22, 109 KeyF23 = GLFW_KEY_F23, 110 KeyF24 = GLFW_KEY_F24, 111 KeyF25 = GLFW_KEY_F25, 112 Keypad0 = GLFW_KEY_KP_0, 113 Keypad1 = GLFW_KEY_KP_1, 114 Keypad2 = GLFW_KEY_KP_2, 115 Keypad3 = GLFW_KEY_KP_3, 116 Keypad4 = GLFW_KEY_KP_4, 117 Keypad5 = GLFW_KEY_KP_5, 118 Keypad6 = GLFW_KEY_KP_6, 119 Keypad7 = GLFW_KEY_KP_7, 120 Keypad8 = GLFW_KEY_KP_8, 121 Keypad9 = GLFW_KEY_KP_9, 122 KeypadDecimal = GLFW_KEY_KP_DECIMAL, 123 KeypadDivide = GLFW_KEY_KP_DIVIDE, 124 KeypadMultiply = GLFW_KEY_KP_MULTIPLY, 125 KeypadSubtract = GLFW_KEY_KP_SUBTRACT, 126 KeypadAdd = GLFW_KEY_KP_ADD, 127 KeypadEnter = GLFW_KEY_KP_ENTER, 128 KeypadEqual = GLFW_KEY_KP_EQUAL, 129 KeyLeftShift = GLFW_KEY_LEFT_SHIFT, 130 KeyLeftControl = GLFW_KEY_LEFT_CONTROL, 131 KeyLeftAlt = GLFW_KEY_LEFT_ALT, 132 KeyLeftSuper = GLFW_KEY_LEFT_SUPER, 133 KeyRightShift = GLFW_KEY_RIGHT_SHIFT, 134 KeyRightControl = GLFW_KEY_RIGHT_CONTROL, 135 KeyRightAlt = GLFW_KEY_RIGHT_ALT, 136 KeyRightSuper = GLFW_KEY_RIGHT_SUPER, 137 KeyMenu = GLFW_KEY_MENU, 138 KeyLast = GLFW_KEY_LAST, 139 140 KeyEsc = GLFW_KEY_ESC, 141 KeyDel = GLFW_KEY_DEL, 142 KeyPgUp = GLFW_KEY_PAGEUP, 143 KeyPgDown = GLFW_KEY_PAGEDOWN, 144 KeypadNumLock = GLFW_KEY_KP_NUM_LOCK, 145 KeyLCtrl = GLFW_KEY_LCTRL, 146 KeyLShift = GLFW_KEY_LSHIFT, 147 KeyLAlt = GLFW_KEY_LALT, 148 KeyLSuper = GLFW_KEY_LSUPER, 149 KeyRCtrl = GLFW_KEY_RCTRL, 150 KeyRShift = GLFW_KEY_RSHIFT, 151 KeyRAlt = GLFW_KEY_RALT, 152 KeyRSuper = GLFW_KEY_RSUPER, 153 } 154 155 /** 156 Keyboard 157 */ 158 class Keyboard { 159 private static: 160 GLFWwindow* window; 161 dchar curChar; 162 163 bool capsLock; 164 bool numLock; 165 166 public static: 167 168 /** 169 Event that is called every time a new text character is typed 170 */ 171 Event!dchar onKeyboardType; 172 173 /** 174 Event that is called every time a new ket event is emitted 175 */ 176 Event!Key onKeyEvent; 177 178 /** 179 Constructs the underlying data needed 180 */ 181 void initialize(GLFWwindow* window) { 182 this.window = window; 183 184 // Create events 185 onKeyboardType = new Event!dchar(); 186 onKeyEvent = new Event!Key(); 187 188 // Do GLFW stuff 189 glfwSetInputMode(window, GLFW_LOCK_KEY_MODS, GLFW_TRUE); 190 glfwSetCharCallback(window, &onCharCallback); 191 glfwSetKeyCallback(window, &onKeyCallback); 192 } 193 194 /** 195 Gets the current typed text character for text input 196 */ 197 dchar getCurrentCharacter() { 198 return curChar; 199 } 200 201 /** 202 Gets whether a key is pressed 203 */ 204 bool isKeyPressed(Key key) { 205 return glfwGetKey(window, key) == GLFW_PRESS; 206 } 207 208 /** 209 Gets whether a key is pressed 210 */ 211 bool isKeyReleased(Key key) { 212 return glfwGetKey(window, key) == GLFW_RELEASE; 213 } 214 215 /** 216 Gets whether CapsLock is on 217 */ 218 bool isCapsLockOn() { 219 return capsLock; 220 } 221 222 /** 223 Gets whether NumLock is on 224 */ 225 bool isNumLockOn() { 226 return numLock; 227 } 228 } 229 230 private: 231 void onKeyEventHandler(Key key) { 232 Keyboard.onKeyEvent(null, key); 233 } 234 235 void onCharEventHandler(dchar key) { 236 Keyboard.onKeyboardType(null, key); 237 } 238 239 nothrow extern(C): 240 void onKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { 241 Keyboard.numLock = (mods & GLFW_MOD_NUM_LOCK) > 0; 242 Keyboard.capsLock = (mods & GLFW_MOD_CAPS_LOCK) > 0; 243 244 // Cursed magic to make our exception throwing D event handler be callable from this C function 245 (cast(void function(Key) nothrow)&onKeyEventHandler)(cast(Key)key); 246 } 247 248 void onCharCallback(GLFWwindow* window, uint codepoint) { 249 Keyboard.curChar = cast(dchar)codepoint; 250 251 // Cursed magic to make our exception throwing D event handler be callable from this C function 252 (cast(void function(dchar) nothrow)&onCharEventHandler)(cast(dchar)codepoint); 253 }