1 module prova.input.input; 2 3 import core.stdc.string; 4 import derelict.sdl2.sdl; 5 import prova.core; 6 import prova.input; 7 import prova.math; 8 9 /// 10 class Input 11 { 12 private Game game; 13 private Vector2 mousePosition; 14 private Controller[int] controllers; 15 private bool[] keystate; 16 private bool[] oldKeystate; 17 private bool[Key] repeatedKeyMap; 18 private bool[] buttonState; 19 private bool[] oldButtonState; 20 private string text = ""; 21 22 package(prova) this(Game game) 23 { 24 this.game = game; 25 26 update(); 27 oldKeystate = keystate; 28 oldButtonState = buttonState; 29 } 30 31 package(prova) void reset() 32 { 33 repeatedKeyMap.clear(); 34 } 35 36 package(prova) void update() 37 { 38 // update controller state 39 foreach(Controller controller; controllers) 40 controller.update(); 41 42 // update keystate 43 oldKeystate = keystate; 44 updateKeystate(); 45 46 // update mouse state 47 int x, y; 48 uint mouseState = SDL_GetMouseState(&x, &y); 49 50 // update button state 51 oldButtonState = buttonState; 52 updateButtonState(mouseState); 53 54 mousePosition.x = -1f + x / (game.screen.width * .5f); 55 mousePosition.y = 1f - y / (game.screen.height * .5f); 56 } 57 58 private void updateKeystate() 59 { 60 int keystateLength; 61 const ubyte* SDLKeystate = SDL_GetKeyboardState(&keystateLength); 62 63 keystate = []; 64 keystate.length = keystateLength; 65 66 (cast(ubyte*)keystate)[0 .. keystateLength][] = SDLKeystate[0 .. keystateLength]; 67 } 68 69 private void updateButtonState(uint mouseState) 70 { 71 buttonState = []; 72 buttonState.length = 5; 73 74 foreach(i; 0 .. 5) { 75 ubyte button = SDL_BUTTON(cast(ubyte) (i + 1)); 76 buttonState[i] = cast(bool) (mouseState & button); 77 } 78 } 79 80 package(prova) void setKeyDown(SDL_Keycode keycode) { 81 Key key = cast(Key) SDL_GetScancodeFromKey(keycode); 82 83 if(isKeyDown(key)) { 84 repeatedKeyMap[key] = true; 85 } 86 } 87 88 package(prova) void updateTextInput(string text) 89 { 90 const bool enteredNewLine = 91 keyJustPressed(Key.KP_ENTER) || isKeyRepeated(Key.KP_ENTER) || 92 keyJustPressed(Key.RETURN) || isKeyRepeated(Key.RETURN); 93 94 if(enteredNewLine) { 95 text ~= '\n'; 96 } 97 98 this.text = text; 99 } 100 101 /// 102 Controller getController(int index) 103 { 104 // controller not found then add it to our list 105 // of updated controllers 106 if(!(index in controllers)) 107 controllers[index] = new Controller(index); 108 109 return controllers[index]; 110 } 111 112 /// Uses the WASD format, returns a normalized vector 113 Vector2 simulateStick(Key up, Key left, Key down, Key right) 114 { 115 Vector2 vector = Vector2( 116 isKeyDown(right) - isKeyDown(left), 117 isKeyDown(up) - isKeyDown(down) 118 ); 119 120 return vector.getNormalized(); 121 } 122 123 /// 124 bool isKeyDown(Key key) 125 { 126 return keystate[cast(int) key]; 127 } 128 129 /// 130 bool isKeyUp(Key key) 131 { 132 return !keystate[cast(int) key]; 133 } 134 135 /// Returns true if the key is pressed and was not pressed in the last tick 136 bool keyJustPressed(Key key) 137 { 138 return !oldKeystate[cast(int) key] && keystate[cast(int) key]; 139 } 140 141 /** 142 * Returns true if a key down event was received before the key was released 143 * Useful for creating text inputs 144 */ 145 bool isKeyRepeated(Key key) 146 { 147 return (key in repeatedKeyMap) != null; 148 } 149 150 /// 151 bool isMouseButtonDown(MouseButton button) 152 { 153 return buttonState[button]; 154 } 155 156 /// 157 bool isMouseButtonUp(MouseButton button) 158 { 159 return !buttonState[button]; 160 } 161 162 /// 163 bool mouseButtonClicked(MouseButton button) 164 { 165 return oldButtonState[button] && !buttonState[button]; 166 } 167 168 /// 169 Vector2 getMousePosition() 170 { 171 return mousePosition; 172 } 173 174 /// 175 void startTextInput() 176 { 177 SDL_StartTextInput(); 178 } 179 180 /// 181 void stopTextInput() 182 { 183 SDL_StopTextInput(); 184 text = ""; 185 } 186 187 /// 188 string getTextInput() 189 { 190 return text; 191 } 192 }