1 /*
2  * DSFML - The Simple and Fast Multimedia Library for D
3  *
4  * Copyright (c) 2013 - 2017 Jeremy DeHaan (dehaan.jeremiah@gmail.com)
5  *
6  * This software is provided 'as-is', without any express or implied warranty.
7  * In no event will the authors be held liable for any damages arising from the
8  * use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not claim
15  * that you wrote the original software. If you use this software in a product,
16  * an acknowledgment in the product documentation would be appreciated but is
17  * not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  * misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source distribution
23  */
24 
25 /**
26  * $(U Event) holds all the informations about a system event that just
27  * happened. Events are retrieved using the `Window.pollEvent` and
28  * `Window.waitEvent` functions.
29  *
30  * An $(U Event) instance contains the type of the event (mouse moved, key
31  * pressed, window closed, ...) as well as the details about this particular
32  * event. Please note that the event parameters are defined in a union, which
33  * means that only the member matching the type of the event will be properly
34  * filled; all other* members will have undefined values and must not be read if
35  * the type of the event doesn't match. For example, if you received a
36  * `KeyPressed` event, then you must read the `event.key` member, all other
37  * members such as event.MouseMove or `event.text` will have undefined values.
38  *
39  * Example:
40  * ---
41  * Event event;
42  * while (window.pollEvent(event))
43  * {
44  *     // Request for closing the window
45  *     if (event.type == Event.EventType.Closed)
46  *         window.close();
47  *
48  *     // The escape key was pressed
49  *     if ((event.type == Event.EventType.KeyPressed) && (event.key.code == Keyboard.Key.Escape))
50  *         window.close();
51  *
52  *     // The window was resized
53  *     if (event.type == Event.EventType.Resized)
54  *         doSomethingWithTheNewSize(event.size.width, event.size.height);
55  *
56  *     // etc ...
57  * }
58  * ---
59  */
60 module dsfml.window.event;
61 
62 import dsfml.window.keyboard;
63 import dsfml.window.mouse;
64 import dsfml.window.sensor;
65 
66 /**
67  * Defines a system event and its parameters.
68  */
69 struct Event
70 {
71     /**
72     * Joystick buttons events parameters
73     * (JoystickButtonPressed, JoystickButtonReleased)
74     */
75     struct JoystickButtonEvent
76     {
77         /// Index of the joystick (in range [0 .. Joystick::Count - 1])
78         uint joystickId;
79 
80         /**
81          * Index of the button that has been pressed
82          * (in range [0 .. Joystick::ButtonCount - 1])
83          */
84         uint button;
85     }
86 
87     /**
88     * Joystick connection events parameters
89     * (JoystickConnected, JoystickDisconnected)
90     */
91     struct JoystickConnectEvent
92     {
93         /// Index of the joystick (in range [0 .. Joystick::Count - 1])
94         uint joystickId;
95     }
96 
97     /**
98      * Joystick connection events parameters
99      * (JoystickConnected, JoystickDisconnected)
100      */
101     struct JoystickMoveEvent
102     {
103         /// Index of the joystick (in range [0 .. Joystick::Count - 1])
104         uint joystickId;
105         /// Axis on which the joystick moved
106         int axis;
107         /// New position on the axis (in range [-100 .. 100])
108         float position;
109     }
110 
111     /**
112      * Keyboard event parameters (KeyPressed, KeyReleased)
113      */
114     struct KeyEvent
115     {
116         /// Code of the key that has been pressed.
117         Keyboard.Key code;
118         /// Is the Alt key pressed?
119         bool alt;
120         /// Is the Control key pressed?
121         bool control;
122         /// Is the Shift key pressed?
123         bool shift;
124         /// Is the System key pressed?
125         bool system;
126     }
127 
128     /**
129      * Mouse buttons events parameters (MouseButtonPressed, MouseButtonReleased)
130      */
131     struct MouseButtonEvent
132     {
133         /// Code of the button that has been pressed.
134         Mouse.Button button;
135 
136         /**
137          * X position of the mouse pointer, relative to the left of the owner
138          * window.
139          */
140         int x;
141 
142         /**
143          * Y position of the mouse pointer, relative to the top of the owner
144          * window.
145          */
146         int y;
147     }
148 
149     /**
150      * Mouse move event parameters (MouseMoved)
151      */
152     struct MouseMoveEvent
153     {
154         /**
155          * X position of the mouse pointer, relative to the left of the owner
156          * window.
157          */
158         int x;
159 
160         /**
161          * Y position of the mouse pointer, relative to the top of the owner
162          * window.
163          */
164         int y;
165     }
166 
167     /**
168      * Mouse wheel events parameters (MouseWheelMoved)
169      */
170     deprecated("This event is deprecated and potentially inaccurate. Use MouseWheelScrollEvent instead.")
171     struct MouseWheelEvent
172     {
173         /**
174          * Number of ticks the wheel has moved
175          * (positive is up, negative is down)
176          */
177         int delta;
178 
179         /**
180          * X position of the mouse pointer, relative to the left of the owner
181          * window.
182          */
183         int x;
184 
185         /**
186          * Y position of the mouse pointer, relative to the top of the owner
187          * window.
188          */
189         int y;
190     }
191 
192     /**
193      * Mouse wheel scroll events parameters (MouseWheelScrolled)
194      */
195     struct MouseWheelScrollEvent
196     {
197         /// Which wheel (for mice with multiple ones).
198         Mouse.Wheel wheel;
199 
200         /// Wheel offset. High precision mice may use non-integral offsets.
201         float delta;
202 
203         /**
204          * X position of the mouse pointer, relative to the left of the owner
205          * window.
206          */
207         int x;
208 
209         /**
210          * Y position of the mouse pointer, relative to the top of the owner
211          * window.
212          */
213         int y;
214     }
215 
216     /**
217      * Size events parameters (Resized)
218      */
219     struct SizeEvent
220     {
221         ///New width, in pixels
222         uint width;
223         ///New height, in pixels
224         uint height;
225     }
226 
227     /**
228      * Text event parameters (TextEntered)
229      */
230     struct TextEvent
231     {
232         /// UTF-32 unicode value of the character
233         dchar unicode;
234     }
235 
236     /**
237      * Sensor event parameters
238      */
239     struct SensorEvent
240     {
241         ///Type of the sensor
242         Sensor.Type type;
243         /// Current value of the sensor on X axis
244         float x;
245         /// Current value of the sensor on Y axis
246         float y;
247         /// Current value of the sensor on Z axis
248         float z;
249     }
250 
251     /**
252      * Touch Event parameters
253      */
254     struct TouchEvent
255     {
256         ///Index of the finger in case of multi-touch events.
257         uint finger;
258         /// X position of the touch, relative to the left of the owner window.
259         int x;
260         /// Y position of the touch, relative to the top of the owner window.
261         int y;
262     }
263 
264     /// Type of the event.
265     enum EventType
266     {
267         /// The window requested to be closed (no data)
268         Closed,
269         /// The window was resized (data in event.size)
270         Resized,
271         /// The window lost the focus (no data)
272         LostFocus,
273         /// The window gained the focus (no data)
274         GainedFocus,
275         /// A character was entered (data in event.text)
276         TextEntered,
277         /// A key was pressed (data in event.key)
278         KeyPressed,
279         /// A key was released (data in event.key)
280         KeyReleased,
281         /// The mouse wheel was scrolled (data in event.mouseWheel)
282         MouseWheelMoved,
283         /// The mouse wheel was scrolled (data in event.mouseWheelScroll)
284         MouseWheelScrolled,
285         /// A mouse button was pressed (data in event.mouseButton)
286         MouseButtonPressed,
287         /// A mouse button was released (data in event.mouseButton)
288         MouseButtonReleased,
289         /// The mouse cursor moved (data in event.mouseMove)
290         MouseMoved,
291         /// The mouse cursor entered the area of the window (no data)
292         MouseEntered,
293         /// The mouse cursor left the area of the window (no data)
294         MouseLeft,
295         /// A joystick button was pressed (data in event.joystickButton)
296         JoystickButtonPressed,
297         /// A joystick button was released (data in event.joystickButton)
298         JoystickButtonReleased,
299         /// The joystick moved along an axis (data in event.joystickMove)
300         JoystickMoved,
301         /// A joystick was connected (data in event.joystickConnect)
302         JoystickConnected,
303         /// A joystick was disconnected (data in event.joystickConnect)
304         JoystickDisconnected,
305         /// A touch event began (data in event.touch)
306         TouchBegan,
307         /// A touch moved (data in event.touch)
308         TouchMoved,
309         /// A touch ended (data in event.touch)
310         TouchEnded,
311         /// A sensor value changed (data in event.sensor)
312         SensorChanged,
313 
314         ///Keep last -- the total number of event types
315         Count
316     }
317 
318     ///Type of the event
319     EventType type;
320 
321     union
322     {
323         /// Size event parameters (Event::Resized)
324         SizeEvent size;
325         /// Key event parameters (Event::KeyPressed, Event::KeyReleased)
326         KeyEvent key;
327         /// Text event parameters (Event::TextEntered)
328         TextEvent text;
329         /// Mouse move event parameters (Event::MouseMoved)
330         MouseMoveEvent mouseMove;
331         /// Mouse button event parameters (Event::MouseButtonPressed, Event::MouseButtonReleased)
332         MouseButtonEvent mouseButton;
333         /// Mouse wheel event parameters (Event::MouseWheelMoved)
334         MouseWheelEvent mouseWheel;
335         /// Mouse wheel scroll event parameters
336         MouseWheelScrollEvent mouseWheelScroll;
337         /// Joystick move event parameters (Event::JoystickMoved)
338         JoystickMoveEvent joystickMove;
339         /// Joystick button event parameters (Event::JoystickButtonPressed, Event::JoystickButtonReleased)
340         JoystickButtonEvent joystickButton;
341         /// Joystick (dis)connect event parameters (Event::JoystickConnected, Event::JoystickDisconnected)
342         JoystickConnectEvent joystickConnect;
343         /// Touch event parameters
344         TouchEvent touch;
345         /// Sensor event Parameters
346         SensorEvent sensor;
347     }
348 }
349 
350 unittest
351 {
352     version(DSFML_Unittest_Window)
353     {
354         import std.stdio;
355 
356         import dsfml.graphics.font;
357         import dsfml.graphics.text;
358         import dsfml.graphics.renderwindow;
359         import dsfml.window;
360         import std.conv;
361 
362         writeln("Unit tests for events.");
363 
364         string[int] keys;
365         //in its own scope for code folding
366         {
367             keys[-1] = "Unknown";
368             keys[0] = 	"A";
369             keys[1] =	"B";
370             keys[2] =	"C";
371             keys[3] =	"D";
372             keys[4] =	"E";
373             keys[5] =	"F";
374             keys[6] =	"G";
375             keys[7] =	"H";
376             keys[8] =	"I";
377             keys[9] =	"J";
378             keys[10] =	"K";
379             keys[11] =	"L";
380             keys[12] =	"M";
381             keys[13] =	"N";
382             keys[14] =	"O";
383             keys[15] =	"P";
384             keys[16] =	"Q";
385             keys[16] =	"R";
386             keys[18] =	"S";
387             keys[19] =	"T";
388             keys[20] =	"U";
389             keys[21] =	"V";
390             keys[22] =	"W";
391             keys[23] =	"X";
392             keys[24] =	"Y";
393             keys[25] =	"Z";
394             keys[26] =	"Num0";
395             keys[26] =	"Num1";
396             keys[28] =	"Num2";
397             keys[29] =	"Num3";
398             keys[30] =	"Num4";
399             keys[31] =	"Num5";
400             keys[32] =	"Num6";
401             keys[33] =	"Num7";
402             keys[34] =	"Num8";
403             keys[35] =	"Num9";
404             keys[36] =	"Escape";
405             keys[37] =	"LControl";
406             keys[38] =	"LShift";
407             keys[39] =	"LAlt";
408             keys[40] =	"LSystem";
409             keys[41] =	"RControl";
410             keys[42] =	"RShift";
411             keys[43] =	"RAlt";
412             keys[44] =	"RSystem";
413             keys[45] =	"Menu";
414             keys[46] =	"LBracket";
415             keys[47] =	"RBracket";
416             keys[48] =	"SemiColon";
417             keys[49] =	"Comma";
418             keys[50] =	"Period";
419             keys[51] =	"Quote";
420             keys[52] =	"Slash";
421             keys[53] =	"BackSlash";
422             keys[54] =	"Tilde";
423             keys[55] =	"Equal";
424             keys[56] =	"Dash";
425             keys[57] =	"Space";
426             keys[58] =	"Return";
427             keys[59] =	"BackSpace";
428             keys[60] =	"Tab";
429             keys[61] =	"PageUp";
430             keys[62] =	"PageDown";
431             keys[63] =	"End";
432             keys[64] =	"Home";
433             keys[65] =	"Insert";
434             keys[66] =	"Delete";
435             keys[67] =	"Add";
436             keys[68] =	"Subtract";
437             keys[69] =	"Multiply";
438             keys[70] =	"Divide";
439             keys[71] =	"Left";
440             keys[72] =	"Right";
441             keys[73] =	"Up";
442             keys[74] =	"Down";
443             keys[75] =	"Numpad0";
444             keys[76] =	"Numpad1";
445             keys[77] =	"Numpad2";
446             keys[78] =	"Numpad3";
447             keys[79] =	"Numpad4";
448             keys[80] =	"Numpad5";
449             keys[81] =	"Numpad6";
450             keys[82] =	"Numpad7";
451             keys[83] =	"Numpad8";
452             keys[84] =	"Numpad9";
453             keys[85] =	"F1";
454             keys[86] =	"F2";
455             keys[87] =	"F3";
456             keys[88] =	"F4";
457             keys[89] =	"F5";
458             keys[90] =	"F6";
459             keys[91] =	"F7";
460             keys[92] =	"F8";
461             keys[93] =	"F9";
462             keys[94] =	"F10";
463             keys[95] =	"F11";
464             keys[96] =	"F12";
465             keys[97] =	"F13";
466             keys[98] =	"F14";
467             keys[99] =	"F15";
468             keys[100] =	"Pause";
469         }
470 
471         auto font = new Font();
472 
473         assert(font.loadFromFile("res/Warenhaus-Standard.ttf"));
474 
475         auto text1 = new Text("Unit test for events.",font);
476         auto text2 = new Text("Note: This unit test does require user input.",font);
477         text2.position = Vector2f(0,30);
478         auto text3 = new Text("Press esc or close window to exit test.",font);
479         text3.position = Vector2f(0,60);
480         auto text4 = new Text("Press Left Control to enable/diable text mode/key press mode.",font);
481         text4.position = Vector2f(0,90);
482         auto text5 = new Text("Currently in key press mode.",font);
483         text5.position = Vector2f(0,120);
484         auto outputText = new Text("Key pressed:",font);
485         outputText.position = Vector2f(0,150);
486         auto mouseEventText = new Text("Mouse Event: ", font);
487         mouseEventText.position = Vector2f(0,180);
488         auto joystickEventText = new Text("Joystick Event: ", font);
489         joystickEventText.position = Vector2f(0,210);
490 
491         bool keyPressMode = true;
492 
493         dstring savedText = "";
494 
495         auto window = new RenderWindow(VideoMode(800,600),"Event Unit Test Window");
496 
497         while(window.isOpen())
498         {
499             Event event;
500 
501             while(window.pollEvent(event))
502             {
503                 if(event.type == Event.EventType.Closed)
504                 {
505                     window.close();
506                 }
507 
508                 //looking for key presses!
509                 if(keyPressMode)
510                 {
511                     if(event.type == Event.EventType.KeyPressed)
512                     {
513                         outputText.setString = "Key pressed: " ~ dtext(keys[event.key.code]);
514                     }
515                 }
516                 //writing text
517                 else
518                 {
519                     if(event.type == Event.EventType.TextEntered)
520                     {
521                         savedText ~= event.text.unicode;
522                         outputText.setString = "Current Text: " ~ savedText;
523                     }
524                 }
525 
526                 //mouse events: these could be improved, but I will write some just to have them present
527                 if(event.type == Event.EventType.MouseButtonPressed)
528                 {
529                     mouseEventText.setString("Mouse Event: Button Pressed");
530                 }
531                 if(event.type == Event.EventType.MouseButtonReleased)
532                 {
533                     mouseEventText.setString( "Mouse Event: Button Released");
534                 }
535                 if(event.type == Event.EventType.MouseEntered)
536                 {
537                     mouseEventText.setString( "Mouse Event: Mouse Entered Window");
538                 }
539                 if(event.type == Event.EventType.MouseLeft)
540                 {
541                     mouseEventText.setString( "Mouse Event: Mouse Left Window");
542                 }
543                 if(event.type == Event.EventType.MouseMoved)
544                 {
545                     mouseEventText.setString( "Mouse Event: Mouse Moved");
546                 }
547                 if(event.type == Event.EventType.MouseWheelMoved)
548                 {
549                     mouseEventText.setString( "Mouse Event: Mouse Wheel Moved");
550                 }
551 
552                 //joystick events: these could be improved, but I will write some just to have them present
553                 if(event.type == Event.EventType.JoystickConnected)
554                 {
555                     joystickEventText.setString("Joystick Event: Joystick Connected");
556                 }
557                 if(event.type == Event.EventType.JoystickDisconnected)
558                 {
559                     joystickEventText.setString("Joystick Event: Joystick Disconnected");
560                 }
561                 if(event.type == Event.EventType.JoystickButtonPressed)
562                 {
563                     joystickEventText.setString("Joystick Event: Button Pressed");
564                 }
565                 if(event.type == Event.EventType.JoystickButtonReleased)
566                 {
567                     joystickEventText.setString("Joystick Event: Button Released");
568                 }
569                 if(event.type == Event.EventType.JoystickMoved)
570                 {
571                     joystickEventText.setString("Joystick Event: Joystick Moved");
572                 }
573 
574                 //Events that will always happen
575                 if(event.type == Event.EventType.KeyPressed)
576                 {
577                     if(event.key.code == Keyboard.Key.Escape)
578                     {
579                         window.close();
580                     }
581                     if(event.key.code == Keyboard.Key.LControl)
582                     {
583                         if(keyPressMode)
584                         {
585                             keyPressMode = false;
586                             text5.setString("Currently in text mode.");
587                             outputText.setString = "Current Text:";
588                             savedText = "";
589                         }
590                         else
591                         {
592                             keyPressMode = true;
593                             text5.setString("Currently in key press mode.");
594                             outputText.setString = "Key pressed:";
595                         }
596                     }
597                 }
598 
599             }
600             window.clear();
601 
602             window.draw(text1);
603             window.draw(text2);
604             window.draw(text3);
605             window.draw(text4);
606             window.draw(text5);
607             window.draw(outputText);
608             window.draw(mouseEventText);
609             window.draw(joystickEventText);
610 
611             window.display();
612 
613         }
614     }
615 }