1 module mutils.events;
2 
3 import core.time;
4 
5 Events gEvents;
6 
7 enum MouseButton {
8 	left = 0,
9 	right = 1,
10 	middle = 2,	
11 }
12 
13 enum Key {
14 	ctrl,
15 	alt,
16 	shift,
17 	F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,
18 	up,down,left,right,
19 	esc
20 }
21 /**
22  * Struct to store simple controller event states, like pressed, down, released.
23  * Supports keyboard and mouse.
24  * Additionaly this object calculates fps.
25  * */
26 struct Events{
27 
28 	bool[256] downKeys;
29 	bool[256] pressedKeys;
30 	bool[256] releasedKeys;
31 	bool[Key.max + 1] downKeysSpecial;
32 	bool[Key.max + 1] pressedKeysSpecial;
33 	bool[Key.max + 1] releasedKeysSpecial;
34 
35 	bool[MouseButton.max + 1] mouseDownKeys;
36 	bool[MouseButton.max + 1] mousePressedKeys;
37 	bool[MouseButton.max + 1] mouseReleasedKeys;
38 	int[2] _mousePos = [100,100];
39 	int[2] _mouseWheel;
40 
41 	alias Clock=MonoTimeImpl!(ClockType.precise);
42 	float dtf;
43 	float fps = 0;
44 	float minTime = 0;
45 	float maxTime = 0;
46 	long oldTime, newTime;
47 
48 	bool quit = false;
49 
50 	void initialzie(){
51 		newTime = Clock.currTime.ticks();
52 	}
53 
54 	long getFrameTimeMsecs(){
55 		return cast(long)(1000f/fps);
56 	}
57 	
58 	void update() {
59 		import core.stdc.string : memset;
60 		_mouseWheel = [0, 0];
61 		memset(&pressedKeys, 0, 256);
62 		memset(&releasedKeys, 0, 256);
63 		memset(&mousePressedKeys, 0, MouseButton.max + 1);
64 		memset(&mouseReleasedKeys, 0, MouseButton.max + 1);
65 		memset(&pressedKeysSpecial, 0, Key.max + 1);
66 		memset(&releasedKeysSpecial, 0, Key.max + 1);
67 		fpsCounter();
68 	}
69 
70 	void fpsCounter() {
71 		static int frames;
72 		static float fpsTimer=0;
73 		static float miTime=0, maTime=0;
74 		long dt;
75 
76 		frames++;
77 		oldTime = newTime;
78 		newTime = Clock.currTime.ticks();
79 		dt = newTime - oldTime;
80 		dtf = cast(float) dt/ Clock.ticksPerSecond;
81 		fpsTimer += dtf;
82 		if (miTime > dtf)
83 			miTime = dtf;
84 		if (maTime < dtf)
85 			maTime = dtf;
86 		if (fpsTimer >= 1) {
87 			minTime = miTime;
88 			maxTime = maTime;
89 			maTime = miTime = dtf;
90 			fps = cast(float)frames / fpsTimer;
91 			fpsTimer -= 1;
92 			frames = 0;
93 		}
94 		
95 	}
96 	
97 	
98 	int[2] mousePos() {
99 		return _mousePos;
100 	}
101 	
102 	int[2] mouseWheel() {
103 		return _mouseWheel;
104 	}
105 	
106 	bool mouseButtonDown(MouseButton b) {
107 		if (mouseDownKeys[b]) {
108 			return true;
109 		}
110 		return false;
111 	}
112 	
113 	bool mouseButtonPressed(MouseButton b) {
114 		
115 		if (mousePressedKeys[b]) {
116 			return true;
117 		}
118 		return false;
119 	}
120 	
121 	bool mouseButtonReleased(MouseButton b) {
122 		if (mouseReleasedKeys[b]) {
123 			return true;
124 		}
125 		return false;
126 	}
127 	
128 	bool keyPressed(short k) {
129 		if (k < 256) {
130 			return pressedKeys[k];
131 		} else {
132 			return false;
133 		}
134 	}
135 	
136 	bool keyReleased(short k) {
137 		if (k < 256) {
138 			return releasedKeys[k];
139 		} else {
140 			return false;
141 		}
142 	}
143 	
144 	bool keyDown(short k) {
145 		if (k < 256) {
146 			return downKeys[k];
147 		} else {
148 			return false;
149 		}
150 	}
151 	
152 	bool keyPressed(Key k) {
153 		if (k < 256) {
154 			return pressedKeysSpecial[k];
155 		} else {
156 			return false;
157 		}
158 	}
159 	
160 	bool keyReleased(Key k) {
161 		if (k < 256) {
162 			return releasedKeysSpecial[k];
163 		} else {
164 			return false;
165 		}
166 	}
167 	
168 	bool keyDown(Key k) {
169 		if (k < 256) {
170 			return downKeysSpecial[k];
171 		} else {
172 			return false;
173 		}
174 	}
175 	///////////////////////////////////////
176 	//// Events check implementations /////
177 	///////////////////////////////////////
178 
179 
180 	//https://dlang.org/blog/2017/02/13/a-new-import-idiom/
181 	// you don't have to import library if you dont use function
182 	template from(string moduleName)
183 	{
184 		mixin("import from = " ~ moduleName ~ ";");
185 	}
186 
187 	void fromSDLEvent()(ref from!"derelict.sdl2.sdl".SDL_Event event){
188 		import derelict.sdl2.sdl;
189 
190 		void specialKeysImpl(uint sym, bool up) {
191 			Key key;
192 			switch (sym) {
193 				//CONTROL ARROWS
194 				case SDLK_UP:key=Key.up;break;
195 				case SDLK_DOWN:key= Key.down;break;
196 				case SDLK_LEFT:key=Key.left;break;
197 				case SDLK_RIGHT:key=Key.right;break;
198 					//CONTROL KEYS
199 				case SDLK_ESCAPE:key=Key.esc;break;
200 				case SDLK_LCTRL:key= Key.ctrl;break;
201 				case SDLK_LSHIFT:key=Key.shift;break;
202 				case SDLK_LALT:key=Key.alt;break;
203 					//F_XX
204 				case SDLK_F1:key=Key.F1;break;
205 				case SDLK_F2:key=Key.F2;break;
206 				case SDLK_F3:key=Key.F3;break;
207 				case SDLK_F4:key=Key.F4;break;
208 				case SDLK_F5:key=Key.F5;break;
209 				case SDLK_F6:key=Key.F6;break;
210 				case SDLK_F7:key=Key.F7;break;
211 				case SDLK_F8:key=Key.F8;break;
212 				case SDLK_F9:key=Key.F9;break;
213 				case SDLK_F10:key=Key.F10;break;
214 				case SDLK_F11:key=Key.F11;break;
215 				case SDLK_F12:key=Key.F12;break;
216 				default:
217 					return;
218 			}
219 			if (!up) {
220 				downKeysSpecial[key] = true;
221 				pressedKeysSpecial[key] = true;
222 			} else {
223 				downKeysSpecial[key] = false;
224 				releasedKeysSpecial[key] = true;
225 			}
226 		}
227 
228 		
229 		switch (event.type) {
230 			case SDL_KEYDOWN:
231 				specialKeysImpl(event.key.keysym.sym, false);
232 				if (event.key.keysym.sym < 256) {
233 					downKeys[event.key.keysym.sym] = true;
234 					pressedKeys[event.key.keysym.sym] = true;
235 				}
236 				
237 				break;
238 			case SDL_KEYUP:
239 				specialKeysImpl(event.key.keysym.sym, true);
240 				if (event.key.keysym.sym < 256) {
241 					downKeys[event.key.keysym.sym] = false;
242 					releasedKeys[event.key.keysym.sym] = true;
243 				}
244 				break;
245 			case SDL_MOUSEBUTTONDOWN:
246 				switch (event.button.button) {
247 					case SDL_BUTTON_LEFT:
248 						mouseDownKeys[MouseButton.left] = true;
249 						mousePressedKeys[MouseButton.left] = true;
250 						break;
251 					case SDL_BUTTON_RIGHT:
252 						mouseDownKeys[MouseButton.right] = true;
253 						mousePressedKeys[MouseButton.right] = true;
254 						break;
255 					case SDL_BUTTON_MIDDLE:
256 						mouseDownKeys[MouseButton.middle] = true;
257 						mousePressedKeys[MouseButton.middle] = true;
258 						break;
259 					default:
260 						break;
261 				}
262 				break;
263 			case SDL_MOUSEBUTTONUP:
264 				switch (event.button.button) {
265 					case SDL_BUTTON_LEFT:
266 						mouseDownKeys[MouseButton.left] = false;
267 						mouseReleasedKeys[MouseButton.left] = true;
268 						break;
269 					case SDL_BUTTON_RIGHT:
270 						mouseDownKeys[MouseButton.right] = false;
271 						mouseReleasedKeys[MouseButton.right] = true;
272 						break;
273 					case SDL_BUTTON_MIDDLE:
274 						mouseDownKeys[MouseButton.middle] = false;
275 						mouseReleasedKeys[MouseButton.middle] = true;
276 						break;
277 					default:
278 						break;
279 				}
280 				break;
281 			case SDL_MOUSEWHEEL:
282 				_mouseWheel[0] = event.wheel.x;
283 				_mouseWheel[1] = event.wheel.y;
284 				
285 				break;
286 			case SDL_QUIT:
287 				gEvents.quit = true;
288 				break;
289 			default:
290 				break;
291 		}
292 		
293 	}
294 
295 
296 
297 
298 
299 }
300