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 }