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);