1 /** 2 * Copyright: Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved 3 * Authors: $(Gabriel Gheorghe) 4 * License: $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007) 5 * Source 6 * Documentation: 7 * Coverage: 8 */ 9 module liberty.core.input; 10 import derelict.sdl2.sdl; 11 import liberty.core.engine; 12 import derelict.sdl2.sdl; 13 import liberty.math.vector; 14 import liberty.core.input; 15 import liberty.core.utils : Singleton, IService; 16 pragma (inline, true): 17 /// 18 class Input : Singleton!Input, IService { 19 private bool _serviceRunning; 20 private { 21 bool[KeyCodeCount] _keyState; 22 bool[KeyCodeCount] _oldKeyState; 23 const _KEY_PRESSED = true; 24 const _KEY_RELEASED = false; 25 SDL_Cursor* _cursorHandle; 26 int _mouseButtonState; 27 int _mouseX = 0; 28 int _mouseY = 0; 29 int _lastMouseX = 0; 30 int _lastMouseY = 0; 31 int _mouseWheelX = 0; 32 int _mouseWheelY = 0; 33 int _mouseDeltaX = 0; 34 int _mouseDeltaY = 0; 35 } 36 package bool _isMouseMoving = false; 37 package bool _isMouseWheeling = false; 38 /// Start Input service. 39 void startService() @trusted { 40 //useSystemCursor(SystemCursor.Arrow); 41 //setCurrentCursor(); 42 _serviceRunning = true; 43 } 44 /// Stop Input service. 45 void stopService() @trusted { 46 if (_cursorHandle !is null) { 47 SDL_FreeCursor(_cursorHandle); 48 _cursorHandle = null; 49 } 50 _serviceRunning = false; 51 } 52 /// Restart Input service. 53 void restartService() @trusted { 54 stopService(); 55 startService(); 56 } 57 /// Returns true if Input service is running. 58 bool isServiceRunning() pure nothrow const @safe @nogc { 59 return _serviceRunning; 60 } 61 /// 62 bool isKeyHold(KeyCode key) { 63 SDL_Scancode scan = SDL_GetScancodeFromKey(cast(SDL_Keycode)key); 64 return _keyState[scan] == _KEY_PRESSED; 65 } 66 /// 67 bool isKeyHold(KeyModFlag key) { 68 SDL_Keymod mod = SDL_GetModState(); 69 if (mod & cast(SDL_Keymod)key) { 70 //_keyState[mod] = _KEY_PRESSED; // TODO. 71 return true; 72 } 73 return false; 74 } 75 /// 76 bool isKeyDown(KeyCode key) { 77 SDL_Scancode scan = SDL_GetScancodeFromKey(cast(SDL_Keycode)key); 78 return markKeyAsJustReleased(scan); 79 } 80 /// 81 bool isKeyNone(KeyCode key) { 82 SDL_Scancode scan = SDL_GetScancodeFromKey(cast(SDL_Keycode)key); 83 return _keyState[scan] == _KEY_RELEASED; 84 } 85 /// 86 bool isKeyUp(KeyCode key) { 87 SDL_Scancode scan = SDL_GetScancodeFromKey(cast(SDL_Keycode)key); 88 bool old_state = (_oldKeyState[scan] == _KEY_PRESSED); 89 _oldKeyState[scan] = _KEY_RELEASED; 90 return (_keyState[scan] == _KEY_RELEASED) && old_state; 91 } 92 private void clearKeys() { _keyState[] = _KEY_RELEASED; } 93 /*package*/ bool markKeyAsPressed(SDL_Scancode scancode) { 94 bool old_state = _keyState[scancode]; 95 _keyState[scancode] = _KEY_PRESSED; 96 return old_state; 97 } 98 /*package*/ bool markKeyAsJustReleased(SDL_Scancode scancode) { 99 bool old_state = _keyState[scancode]; 100 _keyState[scancode] = _KEY_RELEASED; 101 _oldKeyState[scancode] = _KEY_PRESSED; 102 return old_state; 103 } 104 /// Returns current position of the mouse. 105 Vector2I mousePosition() nothrow { 106 return Vector2I(_mouseX, _mouseY); 107 } 108 /// 109 Vector2I lastMousePosition() nothrow { 110 return Vector2I(_lastMouseX, _lastMouseY); 111 } 112 /// Returns previous position of the mouse. 113 Vector2I previousMousePosition() nothrow { 114 return Vector2I(_mouseX - _mouseDeltaX, _mouseY - _mouseDeltaY); 115 } 116 /// Returns the relative direction of the mouse. 117 Vector2I mouseRelativeDirection() nothrow { 118 return Vector2I(_mouseDeltaX, _mouseDeltaY); 119 } 120 /// 121 Vector2I mouseDeltaWheel() nothrow { 122 Vector2I ret = Vector2I(_mouseWheelX, _mouseWheelY); 123 _mouseWheelX = _mouseWheelY = 0; 124 return ret; 125 } 126 /// 127 int mouseDeltaWheelX() nothrow { 128 int ret = _mouseWheelX; 129 _mouseWheelX = 0; 130 return ret; 131 } 132 /// 133 int mouseDeltaWheelY() nothrow { 134 int ret = _mouseWheelY; 135 _mouseWheelY = 0; 136 return ret; 137 } 138 /// 139 bool isMouseButtonPressed(MouseButton button) nothrow { 140 return (_mouseButtonState & SDL_BUTTON(button)) != 0; 141 } 142 /// 143 bool isMouseMoving() nothrow { 144 return _isMouseMoving; 145 } 146 /// 147 bool isMouseScrolling() nothrow { 148 return _isMouseWheeling; 149 } 150 //bool isMouseMoving() nothrow { 151 // return mousePosition() != lastMousePosition(); 152 //} 153 /// Capture the mouse and track input outside the MainWindow. 154 void startMouseCapture() { 155 if (SDL_CaptureMouse(SDL_TRUE) != 0) { 156 //PlatformManager.throwPlatformException("SDL_CaptureMouse"); 157 // TODO: Uncomment. 158 } 159 } 160 /// 161 void stopMouseCapture() { 162 if (SDL_CaptureMouse(SDL_FALSE) != 0) { 163 //PlatformManager.throwPlatformException("SDL_CaptureMouse"); 164 // TODO: Uncomment. 165 } 166 } 167 /*package*/ void updateMouse() { 168 _lastMouseX = _mouseX; 169 _lastMouseY = _mouseY; 170 } 171 /*package*/ void updateMouseMotion(const(SDL_MouseMotionEvent)* event) { 172 _mouseButtonState = SDL_GetMouseState(null, null); 173 _mouseX = event.x; 174 _mouseY = event.y; 175 _mouseDeltaX = event.xrel; 176 _mouseDeltaY = event.yrel; 177 } 178 /*package*/ void updateMouseButtons(const(SDL_MouseButtonEvent)* event) { 179 _mouseButtonState = SDL_GetMouseState(null, null); 180 _mouseX = event.x; 181 _mouseY = event.y; 182 } 183 /*package*/ void updateMouseWheel(const(SDL_MouseWheelEvent)* event) { 184 _mouseButtonState = SDL_GetMouseState(&_mouseX, &_mouseY); 185 _mouseWheelX += event.x; 186 _mouseWheelY += event.y; 187 } 188 /// 189 void useSystemCursor(SystemCursor cursor) { 190 _cursorHandle = SDL_CreateSystemCursor(cast(SDL_SystemCursor)cursor); 191 setCurrentCursor(); 192 } 193 /// 194 void createColorCursor(int h_x, int h_y) { 195 //_cursorHandle = SDL_CreateColorCursor(SurfaceManager.getHandle(), h_x, h_y); 196 // TODO: Uncomment. 197 //if (_cursorHandle is null) { 198 //PlatformManager.throwPlatformException("SDL_CreateColorCursor"); 199 // TODO: Uncomment. 200 //} 201 } 202 /// 203 void lockMouse(bool lock) { 204 //SDL_bool lock_ = cast(SDL_bool)lock; 205 //SDL_ShowCursor(lock_); 206 //SDL_SetWindowGrab(CoreEngine.get.mainWindow._window, lock_); 207 //if ( lock ) { 208 // mouseLock[0] = mouseInfo.xCur; 209 // mouseLock[1] = mouseInfo.yCur; 210 //} 211 } 212 /// 213 void relativeMouseMode(bool relative = true) { 214 SDL_SetRelativeMouseMode(cast(SDL_bool)relative); 215 } 216 /// 217 void windowGrab(bool grabbed = true) { 218 SDL_SetWindowGrab(CoreEngine.get.mainWindow._window, cast(SDL_bool)grabbed); 219 } 220 /// 221 void cursorVisible(bool visible = true) { 222 SDL_ShowCursor(visible); 223 } 224 /// 225 /*package*/ void setCurrentCursor() { 226 SDL_SetCursor(_cursorHandle); 227 } 228 /*package*/ SDL_Cursor* cursorHandle() { 229 return _cursorHandle; 230 } 231 /*package*/ SDL_Cursor* cursor() { 232 SDL_Cursor* cursor_handle = SDL_GetCursor(); 233 if (cursor_handle is null) { 234 //PlatformManager.throwPlatformException("SDL_GetCursor"); 235 // TODO: Uncomment. 236 } 237 return cursor_handle; 238 } 239 /*package*/ SDL_Cursor* defaultCursor() { 240 SDL_Cursor* cursor_handle = SDL_GetDefaultCursor(); 241 if (cursor_handle is null) { 242 //PlatformManager.throwPlatformException("SDL_GetDefaultCursor"); 243 // TODO: Uncomment. 244 } 245 return cursor_handle; 246 } 247 } 248 /// Number of keycodes. 249 enum KeyCodeCount = 512; 250 /// 251 enum KeyCode : int { 252 /// Unknown keycode has value equals to 0. 253 Unknown = SDLK_UNKNOWN, 254 /// Return keycode has value equals to '\r' (carriage return). 255 Return = SDLK_RETURN, 256 /// Esc keycode has value equals to '\033'. 257 Esc = SDLK_ESCAPE, 258 /// Backspace keyword has value equals to '\b'. 259 Backspace = SDLK_BACKSPACE, 260 /// Tab keyword has value equals to '\t'. 261 Tab = SDLK_TAB, 262 /// Space keyword has value equals to ' '. 263 Space = SDLK_SPACE, 264 /// Exclamation keyword has value equals to '!'. 265 Exclamation = SDLK_EXCLAIM, 266 /// 267 DoubleQuote = SDLK_QUOTEDBL, 268 /// 269 Sharp = SDLK_HASH, 270 /// 271 Percent = SDLK_PERCENT, 272 /// 273 Dollar = SDLK_DOLLAR, 274 /// 275 Ampersand = SDLK_AMPERSAND, 276 /// 277 SingleQuote = SDLK_QUOTE, 278 /// 279 LeftParenthesis = SDLK_LEFTPAREN, 280 /// 281 RightParenthesis = SDLK_RIGHTPAREN, 282 /// 283 Star = SDLK_ASTERISK, 284 /// 285 Plus = SDLK_PLUS, 286 /// 287 Comma = SDLK_COMMA, 288 /// 289 Minus = SDLK_MINUS, 290 /// 291 Dot = SDLK_PERIOD, 292 /// 293 Slash = SDLK_SLASH, 294 /// 295 Key0 = SDLK_0, 296 /// 297 Key1 = SDLK_1, 298 /// 299 Key2 = SDLK_2, 300 /// 301 Key3 = SDLK_3, 302 /// 303 Key4 = SDLK_4, 304 /// 305 Key5 = SDLK_5, 306 /// 307 Key6 = SDLK_6, 308 /// 309 Key7 = SDLK_7, 310 /// 311 Key8 = SDLK_8, 312 /// 313 Key9 = SDLK_9, 314 /// 315 Colon = SDLK_COLON, 316 /// 317 Semicolon = SDLK_SEMICOLON, 318 /// 319 Less = SDLK_LESS, 320 /// 321 Equals = SDLK_EQUALS, 322 /// 323 Greater = SDLK_GREATER, 324 /// 325 Question = SDLK_QUESTION, 326 /// 327 MonkeyTail = SDLK_AT, 328 /// 329 LeftBracket = SDLK_LEFTBRACKET, 330 /// 331 Backslash = SDLK_BACKSLASH, 332 /// 333 RightBracket = SDLK_RIGHTBRACKET, 334 /// 335 Caret = SDLK_CARET, 336 /// 337 Underscore = SDLK_UNDERSCORE, 338 /// 339 Backquote = SDLK_BACKQUOTE, 340 /// 341 A = SDLK_a, 342 /// 343 B = SDLK_b, 344 /// 345 C = SDLK_c, 346 /// 347 D = SDLK_d, 348 /// 349 E = SDLK_e, 350 /// 351 F = SDLK_f, 352 /// 353 G = SDLK_g, 354 /// 355 H = SDLK_h, 356 /// 357 I = SDLK_i, 358 /// 359 J = SDLK_j, 360 /// 361 K = SDLK_k, 362 /// 363 L = SDLK_l, 364 /// 365 M = SDLK_m, 366 /// 367 N = SDLK_n, 368 /// 369 O = SDLK_o, 370 /// 371 P = SDLK_p, 372 /// 373 Q = SDLK_q, 374 /// 375 R = SDLK_r, 376 /// 377 S = SDLK_s, 378 /// 379 T = SDLK_t, 380 /// 381 U = SDLK_u, 382 /// 383 V = SDLK_v, 384 /// 385 W = SDLK_w, 386 /// 387 X = SDLK_x, 388 /// 389 Y = SDLK_y, 390 /// 391 Z = SDLK_z, 392 /// 393 CapsLock = SDLK_CAPSLOCK, 394 /// 395 F1 = SDLK_F1, 396 /// 397 F2 = SDLK_F2, 398 /// 399 F3 = SDLK_F3, 400 /// 401 F4 = SDLK_F4, 402 /// 403 F5 = SDLK_F5, 404 /// 405 F6 = SDLK_F6, 406 /// 407 F7 = SDLK_F7, 408 /// 409 F8 = SDLK_F8, 410 /// 411 F9 = SDLK_F9, 412 /// 413 F10 = SDLK_F10, 414 /// 415 F11 = SDLK_F11, 416 /// 417 F12 = SDLK_F12, 418 /// 419 Printsceen = SDLK_PRINTSCREEN, 420 /// 421 ScrollLock = SDLK_SCROLLLOCK, 422 /// 423 Pause = SDLK_PAUSE, 424 /// 425 Insert = SDLK_INSERT, 426 /// 427 Home = SDLK_HOME, 428 /// 429 PageUp = SDLK_PAGEUP, 430 /// 431 Delete = SDLK_DELETE, 432 /// 433 End = SDLK_END, 434 /// 435 PageDown = SDLK_PAGEDOWN, 436 /// 437 Right = SDLK_RIGHT, 438 /// 439 Left = SDLK_LEFT, 440 /// 441 Down = SDLK_DOWN, 442 /// 443 Up = SDLK_UP, 444 /// 445 NumLockClear = SDLK_NUMLOCKCLEAR, 446 /// 447 Divide = SDLK_KP_DIVIDE, 448 /// 449 Multiply = SDLK_KP_MULTIPLY, 450 /// 451 Subtract = SDLK_KP_MINUS, 452 /// 453 Add = SDLK_KP_PLUS, 454 /// 455 Enter = SDLK_KP_ENTER, 456 /// 457 Num1 = SDLK_KP_1, 458 /// 459 Num2 = SDLK_KP_2, 460 /// 461 Num3 = SDLK_KP_3, 462 /// 463 Num4 = SDLK_KP_4, 464 /// 465 Num5 = SDLK_KP_5, 466 /// 467 Num6 = SDLK_KP_6, 468 /// 469 Num7 = SDLK_KP_7, 470 /// 471 Num8 = SDLK_KP_8, 472 /// 473 Num9 = SDLK_KP_9, 474 /// 475 Num0 = SDLK_KP_0, 476 /// 477 Period = SDLK_KP_PERIOD 478 // TODO: Finish. 479 } 480 /// 481 enum KeyModFlag : int { // TODO: Change name? 482 /// 483 None = KMOD_NONE, 484 /// 485 LeftShift = KMOD_LSHIFT, 486 /// 487 RightShift = KMOD_RSHIFT, 488 /// 489 LeftCtrl = KMOD_LCTRL, 490 /// 491 RightCtrl = KMOD_RCTRL, 492 /// 493 LeftAlt = KMOD_LALT, 494 /// 495 RightAlt = KMOD_RALT, 496 /// 497 LeftGUI = KMOD_LGUI, 498 /// 499 RightGUI = KMOD_RGUI, 500 /// 501 Num = KMOD_NUM, 502 /// 503 Caps = KMOD_CAPS, 504 /// 505 Mode = KMOD_MODE, 506 /// 507 Reserved = KMOD_RESERVED, 508 /// 509 Ctrl = KMOD_CTRL, 510 /// 511 Shift = KMOD_SHIFT, 512 /// 513 Alt = KMOD_ALT, 514 /// 515 Gui = KMOD_GUI, 516 } 517 /// 518 enum MouseButton : ubyte { 519 /// 520 Left = SDL_BUTTON_LEFT, 521 /// 522 Middle = SDL_BUTTON_MIDDLE, 523 /// 524 Right = SDL_BUTTON_RIGHT, 525 /// 526 X1 = SDL_BUTTON_X1, 527 /// 528 X2 = SDL_BUTTON_X2, 529 /// 530 LeftMask = SDL_BUTTON_LMASK, 531 /// 532 MiddleMask = SDL_BUTTON_MMASK, 533 /// 534 RightMask = SDL_BUTTON_RMASK, 535 /// 536 X1Mask = SDL_BUTTON_X1MASK, 537 /// 538 X2Mask = SDL_BUTTON_X2MASK 539 } 540 /// All types of supported cursor found in system. 541 enum SystemCursor : int { 542 /// Arrow cursor. 543 Arrow = SDL_SYSTEM_CURSOR_ARROW, 544 /// I-Beam cursor. 545 IBeam = SDL_SYSTEM_CURSOR_IBEAM, 546 /// Wait cursor. 547 Wait = SDL_SYSTEM_CURSOR_WAIT, 548 /// Crosshair cursor. 549 CrossHair = SDL_SYSTEM_CURSOR_CROSSHAIR, 550 /// Small wait cursor. 551 WaitArrow = SDL_SYSTEM_CURSOR_WAITARROW, 552 /// Double arrow pointing northwest and southeast cursor. 553 SizeNWSE = SDL_SYSTEM_CURSOR_SIZENWSE, 554 /// Double arrow pointing northeast and southwest cursor. 555 SizeNESW = SDL_SYSTEM_CURSOR_SIZENESW, 556 /// Double arrow pointing west and east cursor. 557 SizeWE = SDL_SYSTEM_CURSOR_SIZEWE, 558 /// Double arrow pointing north and south cursor. 559 SizeNS = SDL_SYSTEM_CURSOR_SIZENS, 560 /// Four pointed arrow pointing north, south, east and west cursor. 561 SizeAll = SDL_SYSTEM_CURSOR_SIZEALL, 562 /// Slashed circle cursor. 563 No = SDL_SYSTEM_CURSOR_NO, 564 /// Hand cursor. 565 Hand = SDL_SYSTEM_CURSOR_HAND 566 }