1 module des.app.event;
2 
3 public import des.math.linear;
4 
5 import std.traits;
6 import std..string;
7 
8 /++ keyboard event wrap
9  +/
10 struct KeyboardEvent
11 {
12     /// scan code (based on SDL2)
13     enum Scan
14     {
15         UNKNOWN = 0, /// 0
16 
17         A = 4,  /// 4
18         B = 5,  /// 5
19         C = 6,  /// 6
20         D = 7,  /// 7
21         E = 8,  /// 8
22         F = 9,  /// 9
23         G = 10, /// 10
24         H = 11, /// 11
25         I = 12, /// 12
26         J = 13, /// 13
27         K = 14, /// 14
28         L = 15, /// 15
29         M = 16, /// 16
30         N = 17, /// 17
31         O = 18, /// 18
32         P = 19, /// 19
33         Q = 20, /// 20
34         R = 21, /// 21
35         S = 22, /// 22
36         T = 23, /// 23
37         U = 24, /// 24
38         V = 25, /// 25
39         W = 26, /// 26
40         X = 27, /// 27
41         Y = 28, /// 28
42         Z = 29, /// 29
43 
44         NUMBER_1     = 30, /// 30
45         NUMBER_2     = 31, /// 31
46         NUMBER_3     = 32, /// 32
47         NUMBER_4     = 33, /// 33
48         NUMBER_5     = 34, /// 34
49         NUMBER_6     = 35, /// 35
50         NUMBER_7     = 36, /// 36
51         NUMBER_8     = 37, /// 37
52         NUMBER_9     = 38, /// 38
53         NUMBER_0     = 39, /// 39
54 
55         RETURN       = 40, /// 40
56         ESCAPE       = 41, /// 41
57         BACKSPACE    = 42, /// 42
58         TAB          = 43, /// 43
59         SPACE        = 44, /// 44
60 
61         MINUS        = 45, /// 45
62         EQUALS       = 46, /// 46
63         LEFTBRACKET  = 47, /// 47
64         RIGHTBRACKET = 48, /// 48
65         BACKSLASH    = 49, /// 49
66         NONUSHASH    = 50, /// 50
67         SEMICOLON    = 51, /// 51
68         APOSTROPHE   = 52, /// 52
69         GRAVE        = 53, /// 53
70         COMMA        = 54, /// 54
71         PERIOD       = 55, /// 55
72         SLASH        = 56, /// 56
73 
74         CAPSLOCK     = 57, /// 57
75 
76         F1  = 58, /// 58
77         F2  = 59, /// 59
78         F3  = 60, /// 60
79         F4  = 61, /// 61
80         F5  = 62, /// 62
81         F6  = 63, /// 63
82         F7  = 64, /// 64
83         F8  = 65, /// 65
84         F9  = 66, /// 66
85         F10 = 67, /// 67
86         F11 = 68, /// 68
87         F12 = 69, /// 69
88 
89         PRINTSCREEN  = 70, /// 70
90         SCROLLLOCK   = 71, /// 71
91         PAUSE        = 72, /// 72
92         INSERT       = 73, /// 73
93         HOME         = 74, /// 74
94         PAGEUP       = 75, /// 75
95         DELETE       = 76, /// 76
96         END          = 77, /// 77
97         PAGEDOWN     = 78, /// 78
98         RIGHT        = 79, /// 79
99         LEFT         = 80, /// 80
100         DOWN         = 81, /// 81
101         UP           = 82, /// 82
102 
103         NUMLOCKCLEAR = 83, /// 83
104         KP_DIVIDE    = 84, /// 84
105         KP_MULTIPLY  = 85, /// 85
106         KP_MINUS     = 86, /// 86
107         KP_PLUS      = 87, /// 87
108         KP_ENTER     = 88, /// 88
109 
110         KP_1 = 89, /// 89
111         KP_2 = 90, /// 90
112         KP_3 = 91, /// 91
113         KP_4 = 92, /// 92
114         KP_5 = 93, /// 93
115         KP_6 = 94, /// 94
116         KP_7 = 95, /// 95
117         KP_8 = 96, /// 96
118         KP_9 = 97, /// 97
119         KP_0 = 98, /// 98
120 
121         KP_PERIOD = 99, /// 99
122 
123         NONUSBACKSLASH = 100, /// 100
124         APPLICATION    = 101, /// 101
125         POWER          = 102, /// 102
126         KP_EQUALS      = 103, /// 103
127 
128         F13 = 104, /// 104
129         F14 = 105, /// 105
130         F15 = 106, /// 106
131         F16 = 107, /// 107
132         F17 = 108, /// 108
133         F18 = 109, /// 109
134         F19 = 110, /// 110
135         F20 = 111, /// 111
136         F21 = 112, /// 112
137         F22 = 113, /// 113
138         F23 = 114, /// 114
139         F24 = 115, /// 115
140 
141         EXECUTE        = 116, /// 116
142         HELP           = 117, /// 117
143         MENU           = 118, /// 118
144         SELECT         = 119, /// 119
145         STOP           = 120, /// 120
146         AGAIN          = 121, /// 121
147         UNDO           = 122, /// 122
148         CUT            = 123, /// 123
149         COPY           = 124, /// 124
150         PASTE          = 125, /// 125
151         FIND           = 126, /// 126
152         MUTE           = 127, /// 127
153         VOLUMEUP       = 128, /// 128
154         VOLUMEDOWN     = 129, /// 129
155         KP_COMMA       = 133, /// 133
156         KP_EQUALSAS400 = 134, /// 134
157 
158         INTERNATIONAL1 = 135, /// 135
159         INTERNATIONAL2 = 136, /// 136
160         INTERNATIONAL3 = 137, /// 137
161         INTERNATIONAL4 = 138, /// 138
162         INTERNATIONAL5 = 139, /// 139
163         INTERNATIONAL6 = 140, /// 140
164         INTERNATIONAL7 = 141, /// 141
165         INTERNATIONAL8 = 142, /// 142
166         INTERNATIONAL9 = 143, /// 143
167 
168         LANG1 = 144, /// 144
169         LANG2 = 145, /// 145
170         LANG3 = 146, /// 146
171         LANG4 = 147, /// 147
172         LANG5 = 148, /// 148
173         LANG6 = 149, /// 149
174         LANG7 = 150, /// 150
175         LANG8 = 151, /// 151
176         LANG9 = 152, /// 152
177 
178         ALTERASE   = 153, /// 153
179         SYSREQ     = 154, /// 154
180         CANCEL     = 155, /// 155
181         CLEAR      = 156, /// 156
182         PRIOR      = 157, /// 157
183         RETURN2    = 158, /// 158
184         SEPARATOR  = 159, /// 159
185         OUT        = 160, /// 160
186         OPER       = 161, /// 161
187         CLEARAGAIN = 162, /// 162
188         CRSEL      = 163, /// 163
189         EXSEL      = 164, /// 164
190 
191         KP_00  = 176, /// 176
192         KP_000 = 177, /// 177
193 
194         THOUSANDSSEPARATOR = 178, /// 178
195         DECIMALSEPARATOR   = 179, /// 179
196         CURRENCYUNIT       = 180, /// 180
197         CURRENCYSUBUNIT    = 181, /// 181
198         KP_LEFTPAREN       = 182, /// 182
199         KP_RIGHTPAREN      = 183, /// 183
200         KP_LEFTBRACE       = 184, /// 184
201         KP_RIGHTBRACE      = 185, /// 185
202         KP_TAB             = 186, /// 186
203         KP_BACKSPACE       = 187, /// 187
204         KP_A = 188, /// 188
205         KP_B = 189, /// 189
206         KP_C = 190, /// 190
207         KP_D = 191, /// 191
208         KP_E = 192, /// 192
209         KP_F = 193, /// 193
210         KP_XOR            = 194, /// 194
211         KP_POWER          = 195, /// 195
212         KP_PERCENT        = 196, /// 196
213         KP_LESS           = 197, /// 197
214         KP_GREATER        = 198, /// 198
215         KP_AMPERSAND      = 199, /// 199
216         KP_DBLAMPERSAND   = 200, /// 200
217         KP_VERTICALBAR    = 201, /// 201
218         KP_DBLVERTICALBAR = 202, /// 202
219         KP_COLON          = 203, /// 203
220         KP_HASH           = 204, /// 204
221         KP_SPACE          = 205, /// 205
222         KP_AT             = 206, /// 206
223         KP_EXCLAM         = 207, /// 207
224         KP_MEMSTORE       = 208, /// 208
225         KP_MEMRECALL      = 209, /// 209
226         KP_MEMCLEAR       = 210, /// 210
227         KP_MEMADD         = 211, /// 211
228         KP_MEMSUBTRACT    = 212, /// 212
229         KP_MEMMULTIPLY    = 213, /// 213
230         KP_MEMDIVIDE      = 214, /// 214
231         KP_PLUSMINUS      = 215, /// 215
232         KP_CLEAR          = 216, /// 216
233         KP_CLEARENTRY     = 217, /// 217
234         KP_BINARY         = 218, /// 218
235         KP_OCTAL          = 219, /// 219
236         KP_DECIMAL        = 220, /// 220
237         KP_HEXADECIMAL    = 221, /// 221
238 
239         LCTRL  = 224, /// 224
240         LSHIFT = 225, /// 225
241         LALT   = 226, /// 226
242         LGUI   = 227, /// 227
243         RCTRL  = 228, /// 228
244         RSHIFT = 229, /// 229
245         RALT   = 230, /// 230
246         RGUI   = 231, /// 231
247 
248         MODE = 257, /// 257
249 
250         AUDIONEXT    = 258, /// 258
251         AUDIOPREV    = 259, /// 259
252         AUDIOSTOP    = 260, /// 260
253         AUDIOPLAY    = 261, /// 261
254         AUDIOMUTE    = 262, /// 262
255         MEDIASELECT  = 263, /// 263
256         WWW          = 264, /// 264
257         MAIL         = 265, /// 265
258         CALCULATOR   = 266, /// 266
259         COMPUTER     = 267, /// 267
260         AC_SEARCH    = 268, /// 268
261         AC_HOME      = 269, /// 269
262         AC_BACK      = 270, /// 270
263         AC_FORWARD   = 271, /// 271
264         AC_STOP      = 272, /// 272
265         AC_REFRESH   = 273, /// 273
266         AC_BOOKMARKS = 274, /// 274
267 
268         BRIGHTNESSDOWN = 275, /// 275
269         BRIGHTNESSUP   = 276, /// 276
270         DISPLAYSWITCH  = 277, /// 277
271         KBDILLUMTOGGLE = 278, /// 278
272         KBDILLUMDOWN   = 279, /// 279
273         KBDILLUMUP     = 280, /// 280
274         EJECT          = 281, /// 281
275         SLEEP          = 282, /// 282
276 
277         APP1 = 283, /// 283
278         APP2 = 284, /// 284
279 
280         NUM_SCANCODES = 512 /// 512
281     }
282 
283     /// Modificators (SHIFT, ALT etc)
284     enum Mod
285     {
286         NONE   = 0x0000,          /// 0x0000
287         LSHIFT = 0x0001,          /// 0x0001
288         RSHIFT = 0x0002,          /// 0x0002
289         LCTRL  = 0x0040,          /// 0x0040
290         RCTRL  = 0x0080,          /// 0x0080
291         LALT   = 0x0100,          /// 0x0100
292         RALT   = 0x0200,          /// 0x0200
293         LGUI   = 0x0400,          /// 0x0400
294         RGUI   = 0x0800,          /// 0x0800
295         NUM    = 0x1000,          /// 0x1000
296         CAPS   = 0x2000,          /// 0x2000
297         MODE   = 0x4000,          /// 0x4000
298         CTRL   = (LCTRL|RCTRL),   /// (LCTRL|RCTRL)
299         SHIFT  = (LSHIFT|RSHIFT), /// (LSHIFT|RSHIFT)
300         ALT    = (LALT|RALT),     /// (LALT|RALT)
301         GUI    = (LGUI|RGUI),     /// (LGUI|RGUI)
302     }
303 
304     /// is key pressed
305     bool pressed;
306 
307     /// is this event a repeat
308     bool repeat;
309 
310     ///
311     Scan scan;
312 
313     /// 
314     uint key;
315 
316     ///
317     Mod mod;
318 }
319 
320 ///
321 alias in_KeyboardEvent = ref const(KeyboardEvent);
322 
323 /// add binary flag
324 T binAdd(T)( in T a, in T b ) if( isIntegral!T ) { return a | b; }
325 
326 /// remove binary flag
327 T binRemove(T)( in T a, in T b ) if( isIntegral!T ) { return a ^ ( a & b ); }
328 
329 /// find binary flag
330 bool binHas(T)( in T a, in T b ) if( isIntegral!T ) { return ( a & b ) == b; }
331 
332 unittest
333 {
334     auto a = 0b0001;
335     auto b = 0b0010;
336     auto c = binAdd(a,b);
337     assert( c == 0b0011 );
338     assert( binRemove(c,a) == b );
339     assert( binRemove(c,b) == a );
340     assert( binHas(c,a) );
341     assert( binHas(c,b) );
342     auto x = 0b0100;
343     assert( !binHas(c,x) );
344 }
345 
346 ///
347 struct MouseEvent
348 {
349     ///
350     enum Type
351     {
352         PRESSED, ///
353         RELEASED,///
354         MOTION,  ///
355         WHEEL    ///
356     };
357 
358     ///
359     enum Button
360     {
361         NONE   = 0,    /// 0
362         LEFT   = 1<<0, /// 1
363         MIDDLE = 1<<1, /// 2
364         RIGHT  = 1<<2, /// 4
365         X1     = 1<<3, /// 8
366         X2     = 1<<4, /// 16
367     }
368 
369     ///
370     Type type; 
371 
372     /// mouse button
373     Button btn = Button.NONE;
374 
375     /// mask for motion, button for pressed/released, 0 for wheel
376     uint mask;
377 
378     /// current pos
379     ivec2 pos;
380     /// different between last and current pos
381     ivec2 rel;
382 
383     /// pressed button motion pos
384     ivec2[[EnumMembers!Button].length-1] posPress;
385     /// pressed button relative motion (different between last and current)
386     ivec2[[EnumMembers!Button].length-1] relPress;
387 
388     /// wheel
389     ivec2 whe;
390 
391     ///
392     ivec2 getPosPress( Button b ) const
393     {
394         if( b == Button.NONE ) return pos;
395         return posPress[buttonIndex(b)];
396     }
397 
398     ///
399     ivec2 getRelPress( Button b ) const
400     {
401         if( b == Button.NONE ) return ivec2(0,0);
402         return relPress[buttonIndex(b)];
403     }
404 
405     /// is button pressed
406     bool isPressed( Button b ) const
407     { return binHas( mask, b ); }
408 
409     /// append button to mask
410     void appendButton( uint b ) { mask = binAdd( mask, b ); }
411 
412     /// remove button to mask
413     void removeButton( uint b ) { mask = binRemove( mask, b ); }
414 
415     /// index in `posPress` and `relPress`
416     static size_t buttonIndex( Button b )
417     {
418         foreach( i, lb; [EnumMembers!Button][1..$] )
419             if( lb == b ) return i;
420         assert(0,format("%s has no index",b));
421     }
422 }
423 
424 ///
425 alias in_MouseEvent = ref const(MouseEvent);