1 //
2 // ID Engine
3 // ID_IN.c - Input Manager
4 // v1.0d1
5 // By Jason Blochowiak
6 //
7
8 //
9 // This module handles dealing with the various input devices
10 //
11 // Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
12 // User Mgr (for command line parms)
13 //
14 // Globals:
15 // LastScan - The keyboard scan code of the last key pressed
16 // LastASCII - The ASCII value of the last key pressed
17 // DEBUG - there are more globals
18 //
19
20
21 #include "wl_def.h"
22 #include "c_cvars.h"
23 #include "id_sd.h"
24 #include "id_in.h"
25 #include "id_vl.h"
26 #include "id_vh.h"
27 #include "config.h"
28 #include "wl_play.h"
29
30
31 #if !SDL_VERSION_ATLEAST(1,3,0)
32 #define SDLK_KP_0 SDLK_KP0
33 #define SDLK_KP_1 SDLK_KP1
34 #define SDLK_KP_2 SDLK_KP2
35 #define SDLK_KP_3 SDLK_KP3
36 #define SDLK_KP_4 SDLK_KP4
37 #define SDLK_KP_5 SDLK_KP5
38 #define SDLK_KP_6 SDLK_KP6
39 #define SDLK_KP_7 SDLK_KP7
40 #define SDLK_KP_8 SDLK_KP8
41 #define SDLK_KP_9 SDLK_KP9
42 #define SDLK_SCROLLLOCK SDLK_SCROLLOCK
43 #define SDL_NUM_SCANCODES SDLK_LAST
44 typedef SDLMod SDL_Keymod;
45
SDL_SetRelativeMouseMode(bool enabled)46 inline void SDL_SetRelativeMouseMode(bool enabled)
47 {
48 SDL_WM_GrabInput(enabled ? SDL_GRAB_ON : SDL_GRAB_OFF);
49 }
SDL_WarpMouseInWindow(struct SDL_Window * window,int x,int y)50 inline void SDL_WarpMouseInWindow(struct SDL_Window* window, int x, int y)
51 {
52 SDL_WarpMouse(x, y);
53 }
54 #endif
55
56 #ifdef _WIN32
57 // SDL doesn't track the real state of the numlock or capslock key, so we need
58 // to query the system. It's probably like this since Linux and OS X don't
59 // appear to have nice APIs for this.
60 void I_CheckKeyMods();
61 #endif
62
63 /*
64 =============================================================================
65
66 GLOBAL VARIABLES
67
68 =============================================================================
69 */
70
71
72 //
73 // configuration variables
74 //
75 bool MousePresent;
76
77
78 // Global variables
79 volatile bool Keyboard[SDL_NUM_SCANCODES];
80 volatile unsigned short Paused;
81 volatile char LastASCII;
82 volatile ScanCode LastScan;
83
84 static KeyboardDef KbdDefs = {
85 sc_Control, // button0
86 sc_Alt, // button1
87 sc_Home, // upleft
88 sc_UpArrow, // up
89 sc_PgUp, // upright
90 sc_LeftArrow, // left
91 sc_RightArrow, // right
92 sc_End, // downleft
93 sc_DownArrow, // down
94 sc_PgDn // downright
95 };
96
97 static SDL_Joystick *Joystick;
98 #if SDL_VERSION_ATLEAST(2,0,0)
99 static SDL_GameController *GameController;
100 // Flip the right stick axes to match usual mapping of Joystick API.
101 static SDL_GameControllerAxis GameControllerAxisMap[SDL_CONTROLLER_AXIS_MAX] = {
102 SDL_CONTROLLER_AXIS_LEFTX, SDL_CONTROLLER_AXIS_LEFTY, // X, Y
103 SDL_CONTROLLER_AXIS_RIGHTY, SDL_CONTROLLER_AXIS_RIGHTX, // Z, R
104 SDL_CONTROLLER_AXIS_TRIGGERLEFT, SDL_CONTROLLER_AXIS_TRIGGERRIGHT
105 };
106 #endif
107 JoystickSens *JoySensitivity;
108 int JoyNumButtons;
109 int JoyNumAxes;
110 static int JoyNumHats;
111
112 static bool GrabInput = false;
113
114 /*
115 =============================================================================
116
117 LOCAL VARIABLES
118
119 =============================================================================
120 */
121 static bool IN_Started;
122
123 static Direction DirTable[] = // Quick lookup for total direction
124 {
125 dir_NorthWest, dir_North, dir_NorthEast,
126 dir_West, dir_None, dir_East,
127 dir_SouthWest, dir_South, dir_SouthEast
128 };
129
130
131 ///////////////////////////////////////////////////////////////////////////
132 //
133 // INL_GetMouseButtons() - Gets the status of the mouse buttons from the
134 // mouse driver
135 //
136 ///////////////////////////////////////////////////////////////////////////
137 static int
INL_GetMouseButtons(void)138 INL_GetMouseButtons(void)
139 {
140 int buttons = SDL_GetMouseState(NULL, NULL);
141 int middlePressed = buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE);
142 int rightPressed = buttons & SDL_BUTTON(SDL_BUTTON_RIGHT);
143 buttons &= ~(SDL_BUTTON(SDL_BUTTON_MIDDLE) | SDL_BUTTON(SDL_BUTTON_RIGHT));
144 if(middlePressed) buttons |= 1 << 2;
145 if(rightPressed) buttons |= 1 << 1;
146
147 return buttons;
148 }
149
150 ///////////////////////////////////////////////////////////////////////////
151 //
152 // IN_GetJoyDelta() - Returns the relative movement of the specified
153 // joystick (from +/-127)
154 //
155 ///////////////////////////////////////////////////////////////////////////
IN_GetJoyDelta(int * dx,int * dy)156 void IN_GetJoyDelta(int *dx,int *dy)
157 {
158 if(!IN_JoyPresent())
159 {
160 *dx = *dy = 0;
161 return;
162 }
163
164 int x, y;
165 #if SDL_VERSION_ATLEAST(2,0,0)
166 if(GameController)
167 {
168 SDL_GameControllerUpdate();
169 x = SDL_GameControllerGetAxis(GameController, SDL_CONTROLLER_AXIS_LEFTX) >> 8;
170 y = SDL_GameControllerGetAxis(GameController, SDL_CONTROLLER_AXIS_LEFTY) >> 8;
171
172 if(SDL_GameControllerGetButton(GameController, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
173 x += 127;
174 else if(SDL_GameControllerGetButton(GameController, SDL_CONTROLLER_BUTTON_DPAD_LEFT))
175 x -= 127;
176 if(SDL_GameControllerGetButton(GameController, SDL_CONTROLLER_BUTTON_DPAD_DOWN))
177 y += 127;
178 else if(SDL_GameControllerGetButton(GameController, SDL_CONTROLLER_BUTTON_DPAD_UP))
179 y -= 127;
180 }
181 else
182 #endif
183 {
184 SDL_JoystickUpdate();
185 x = SDL_JoystickGetAxis(Joystick, 0) >> 8;
186 y = SDL_JoystickGetAxis(Joystick, 1) >> 8;
187
188 if(param_joystickhat != -1)
189 {
190 uint8_t hatState = SDL_JoystickGetHat(Joystick, param_joystickhat);
191 if(hatState & SDL_HAT_RIGHT)
192 x += 127;
193 else if(hatState & SDL_HAT_LEFT)
194 x -= 127;
195 if(hatState & SDL_HAT_DOWN)
196 y += 127;
197 else if(hatState & SDL_HAT_UP)
198 y -= 127;
199 }
200 }
201
202 if(x < -128) x = -128;
203 else if(x > 127) x = 127;
204
205 if(y < -128) y = -128;
206 else if(y > 127) y = 127;
207
208 *dx = x;
209 *dy = y;
210 }
211
IN_GetJoyAxis(int axis)212 int IN_GetJoyAxis(int axis)
213 {
214 #if SDL_VERSION_ATLEAST(2,0,0)
215 if(GameController)
216 return SDL_GameControllerGetAxis(GameController, GameControllerAxisMap[axis]);
217 #endif
218 return SDL_JoystickGetAxis(Joystick, axis);
219 }
220
221 /*
222 ===================
223 =
224 = IN_JoyButtons
225 =
226 ===================
227 */
228
IN_JoyButtons()229 int IN_JoyButtons()
230 {
231 #if SDL_VERSION_ATLEAST(2,0,0)
232 if(GameController)
233 {
234 SDL_GameControllerUpdate();
235
236 int res = 0;
237 for(int i = 0; i < JoyNumButtons; ++i)
238 {
239 if(SDL_GameControllerGetButton(GameController, (SDL_GameControllerButton)i))
240 {
241 // Attempt to allow controllers using the game controller API
242 // to enter the menu.
243 if(i == SDL_CONTROLLER_BUTTON_START)
244 buttonstate[bt_esc] = true;
245 else
246 res |= 1<<i;
247 }
248 }
249 return res;
250 }
251 #endif
252
253 if(!Joystick) return 0;
254
255 SDL_JoystickUpdate();
256
257 int res = 0;
258 int i;
259 for(i = 0; i < JoyNumButtons && i < 32; i++)
260 res |= SDL_JoystickGetButton(Joystick, i) << i;
261
262 // Need four buttons for hat
263 if(i < 28 && param_joystickhat != -1)
264 {
265 uint8_t hatState = SDL_JoystickGetHat(Joystick, param_joystickhat);
266 if(hatState & SDL_HAT_UP)
267 res |= 0x1 << i;
268 else if(hatState & SDL_HAT_DOWN)
269 res |= 0x4 << i;
270 if(hatState & SDL_HAT_RIGHT)
271 res |= 0x2 << i;
272 else if(hatState & SDL_HAT_LEFT)
273 res |= 0x8 << i;
274 }
275 return res;
276 }
277
IN_JoyAxes()278 int IN_JoyAxes()
279 {
280 #if SDL_VERSION_ATLEAST(2,0,0)
281 if(GameController)
282 {
283 SDL_GameControllerUpdate();
284 int res = 0;
285 for(int i = 0; i < JoyNumAxes; ++i)
286 {
287 SWORD pos = SDL_GameControllerGetAxis(GameController, (SDL_GameControllerAxis)GameControllerAxisMap[i]);
288 if(pos <= -0x1000)
289 res |= 1 << (i*2);
290 else if(pos >= 0x1000)
291 res |= 1 << (i*2+1);
292 }
293 return res;
294 }
295 #endif
296 if(!Joystick) return 0;
297
298 SDL_JoystickUpdate();
299
300 int res = 0;
301 for(int i = 0; i < JoyNumAxes && i < 16; ++i)
302 {
303 SWORD pos = SDL_JoystickGetAxis(Joystick, i);
304 if(pos <= -0x1000)
305 res |= 1 << (i*2);
306 else if(pos >= 0x1000)
307 res |= 1 << (i*2+1);
308 }
309 return res;
310 }
311
IN_JoyPresent()312 bool IN_JoyPresent()
313 {
314 return Joystick != NULL
315 #if SDL_VERSION_ATLEAST(2,0,0)
316 || GameController != NULL
317 #endif
318 ;
319 }
320
321 #ifdef __ANDROID__
322 static bool ShadowKey = false;
323 bool ShadowingEnabled = false;
324 extern "C" int hasHardwareKeyboard();
325 #endif
326
processEvent(SDL_Event * event)327 static void processEvent(SDL_Event *event)
328 {
329 switch (event->type)
330 {
331 // exit if the window is closed
332 case SDL_QUIT:
333 Quit(NULL);
334
335 // ASCII (Unicode) text entry for saves and stuff like that.
336 #if SDL_VERSION_ATLEAST(1,3,0)
337 case SDL_TEXTINPUT:
338 {
339 LastASCII = event->text.text[0];
340 break;
341 }
342 #endif
343
344 // check for keypresses
345 case SDL_KEYDOWN:
346 {
347 if(event->key.keysym.sym==SDLK_SCROLLLOCK)
348 {
349 GrabInput = !GrabInput;
350 SDL_SetRelativeMouseMode(GrabInput ? SDL_TRUE : SDL_FALSE);
351 return;
352 }
353
354 #if SDL_VERSION_ATLEAST(1,3,0)
355 LastScan = event->key.keysym.scancode;
356 #else
357 LastScan = event->key.keysym.sym;
358 #endif
359 SDL_Keymod mod = SDL_GetModState();
360 if(Keyboard[sc_Alt])
361 {
362 if(LastScan==SDLx_SCANCODE(F4))
363 Quit(NULL);
364 }
365
366 if(LastScan == SDLx_SCANCODE(KP_ENTER)) LastScan = SDLx_SCANCODE(RETURN);
367 else if(LastScan == SDLx_SCANCODE(RSHIFT)) LastScan = SDLx_SCANCODE(LSHIFT);
368 else if(LastScan == SDLx_SCANCODE(RALT)) LastScan = SDLx_SCANCODE(LALT);
369 else if(LastScan == SDLx_SCANCODE(RCTRL)) LastScan = SDLx_SCANCODE(LCTRL);
370 else
371 {
372 if((mod & KMOD_NUM) == 0)
373 {
374 switch(LastScan)
375 {
376 case SDLx_SCANCODE(KP_2): LastScan = SDLx_SCANCODE(DOWN); break;
377 case SDLx_SCANCODE(KP_4): LastScan = SDLx_SCANCODE(LEFT); break;
378 case SDLx_SCANCODE(KP_6): LastScan = SDLx_SCANCODE(RIGHT); break;
379 case SDLx_SCANCODE(KP_8): LastScan = SDLx_SCANCODE(UP); break;
380 }
381 }
382 }
383
384 #if !SDL_VERSION_ATLEAST(1,3,0)
385 static const byte ASCIINames[] = // Unshifted ASCII for scan codes // TODO: keypad
386 {
387 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
388 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,8 ,9 ,0 ,0 ,0 ,13 ,0 ,0 , // 0
389 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,27 ,0 ,0 ,0 , // 1
390 ' ',0 ,0 ,0 ,0 ,0 ,0 ,39 ,0 ,0 ,'*','+',',','-','.','/', // 2
391 '0','1','2','3','4','5','6','7','8','9',0 ,';',0 ,'=',0 ,0 , // 3
392 '`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', // 4
393 'p','q','r','s','t','u','v','w','x','y','z','[',92 ,']',0 ,0 , // 5
394 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
395 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
396 };
397 static const byte ShiftNames[] = // Shifted ASCII for scan codes
398 {
399 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
400 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,8 ,9 ,0 ,0 ,0 ,13 ,0 ,0 , // 0
401 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,27 ,0 ,0 ,0 , // 1
402 ' ',0 ,0 ,0 ,0 ,0 ,0 ,34 ,0 ,0 ,'*','+','<','_','>','?', // 2
403 ')','!','@','#','$','%','^','&','*','(',0 ,':',0 ,'+',0 ,0 , // 3
404 '~','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', // 4
405 'P','Q','R','S','T','U','V','W','X','Y','Z','{','|','}',0 ,0 , // 5
406 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
407 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
408 };
409
410 int sym = event->key.keysym.sym;
411 if(sym >= 'a' && sym <= 'z')
412 sym -= 32; // convert to uppercase
413
414 if(mod & KMOD_SHIFT)
415 {
416 if((unsigned)sym < lengthof(ShiftNames) && ShiftNames[sym])
417 LastASCII = ShiftNames[sym];
418 }
419 else
420 {
421 if((unsigned)sym < lengthof(ASCIINames) && ASCIINames[sym])
422 LastASCII = ASCIINames[sym];
423 }
424 if(LastASCII && sym >= 'A' && sym <= 'Z' && (mod & KMOD_CAPS))
425 LastASCII ^= 0x20;
426 #endif
427
428 if(LastScan<SDL_NUM_SCANCODES)
429 Keyboard[LastScan] = 1;
430 if(LastScan == SDLx_SCANCODE(PAUSE))
431 Paused |= 1;
432 break;
433 }
434
435 case SDL_KEYUP:
436 {
437 #if SDL_VERSION_ATLEAST(1,3,0)
438 int key = event->key.keysym.scancode;
439 #else
440 int key = event->key.keysym.sym;
441 #endif
442 if(key == SDLx_SCANCODE(KP_ENTER)) key = SDLx_SCANCODE(RETURN);
443 else if(key == SDLx_SCANCODE(RSHIFT)) key = SDLx_SCANCODE(LSHIFT);
444 else if(key == SDLx_SCANCODE(RALT)) key = SDLx_SCANCODE(LALT);
445 else if(key == SDLx_SCANCODE(RCTRL)) key = SDLx_SCANCODE(LCTRL);
446 else
447 {
448 if((SDL_GetModState() & KMOD_NUM) == 0)
449 {
450 switch(key)
451 {
452 case SDLx_SCANCODE(KP_2): key = SDLx_SCANCODE(DOWN); break;
453 case SDLx_SCANCODE(KP_4): key = SDLx_SCANCODE(LEFT); break;
454 case SDLx_SCANCODE(KP_6): key = SDLx_SCANCODE(RIGHT); break;
455 case SDLx_SCANCODE(KP_8): key = SDLx_SCANCODE(UP); break;
456 }
457 }
458 }
459
460 #ifdef __ANDROID__
461 if(ShadowKey && LastScan == event->key.keysym.scancode)
462 {
463 ShadowKey = false;
464 break;
465 }
466 #endif
467
468 if(key<SDL_NUM_SCANCODES)
469 Keyboard[key] = 0;
470 break;
471 }
472
473 #if !SDL_VERSION_ATLEAST(1,3,0)
474 case SDL_ACTIVEEVENT:
475 {
476 if (!fullscreen && forcegrabmouse && (event->active.state & SDL_APPINPUTFOCUS || event->active.state & SDL_APPACTIVE))
477 {
478 // Release the mouse if we lose input focus, grab it again
479 // when we gain input focus.
480 if (event->active.gain == 1)
481 {
482 IN_GrabMouse();
483 }
484 else
485 {
486 IN_ReleaseMouse();
487 }
488 }
489 break;
490 }
491 #else
492 #ifdef _WIN32
493 case SDL_WINDOWEVENT:
494 if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
495 I_CheckKeyMods();
496 break;
497 #endif
498 #endif
499 }
500 }
501
IN_WaitAndProcessEvents()502 void IN_WaitAndProcessEvents()
503 {
504 SDL_Event event;
505 if(!SDL_WaitEvent(&event)) return;
506 do
507 {
508 processEvent(&event);
509 }
510 while(SDL_PollEvent(&event));
511 }
512
IN_ProcessEvents()513 void IN_ProcessEvents()
514 {
515 SDL_Event event;
516
517 #ifdef __ANDROID__
518 if(ShadowingEnabled)
519 {
520 if(!ShadowKey)
521 Keyboard[LastScan] = 0;
522 ShadowKey = true;
523 }
524 #endif
525
526 while (SDL_PollEvent(&event))
527 {
528 processEvent(&event);
529 }
530 }
531
532
533 ///////////////////////////////////////////////////////////////////////////
534 //
535 // IN_Startup() - Starts up the Input Mgr
536 //
537 ///////////////////////////////////////////////////////////////////////////
538 void
IN_Startup(void)539 IN_Startup(void)
540 {
541 if (IN_Started)
542 return;
543
544 #ifdef __ANDROID__
545 ShadowingEnabled = !hasHardwareKeyboard();
546 #endif
547
548 #ifdef _WIN32
549 I_CheckKeyMods();
550 #else
551 // Turn numlock on by default since that's probably what most people want.
552 SDL_SetModState(SDL_Keymod(SDL_GetModState()|KMOD_NUM));
553 #endif
554
555 IN_ClearKeysDown();
556
557 if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) == 0 &&
558 param_joystickindex >= 0 && param_joystickindex < SDL_NumJoysticks())
559 {
560 #if SDL_VERSION_ATLEAST(2,0,0)
561 if(SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == 0 && SDL_IsGameController(param_joystickindex))
562 {
563 GameController = SDL_GameControllerOpen(param_joystickindex);
564 if(GameController)
565 {
566 Printf("Using game controller: %s\n", SDL_GameControllerName(GameController));
567 SDL_GameControllerEventState(SDL_IGNORE);
568 JoyNumButtons = SDL_CONTROLLER_BUTTON_MAX;
569 JoyNumAxes = SDL_CONTROLLER_AXIS_MAX;
570 JoyNumHats = 0;
571
572 JoySensitivity = new JoystickSens[JoyNumAxes];
573 }
574 }
575 else
576 #endif
577 {
578 Joystick = SDL_JoystickOpen(param_joystickindex);
579 if(Joystick)
580 {
581 JoyNumButtons = SDL_JoystickNumButtons(Joystick);
582 if(JoyNumButtons > 32) JoyNumButtons = 32; // only up to 32 buttons are supported
583 JoyNumAxes = SDL_JoystickNumAxes(Joystick);
584 JoyNumHats = SDL_JoystickNumHats(Joystick);
585 if(param_joystickhat >= JoyNumHats)
586 Quit("The joystickhat param must be between 0 and %i!", JoyNumHats - 1);
587 else if(param_joystickhat < 0 && JoyNumHats > 0) // Default to hat 0
588 param_joystickhat = 0;
589
590 JoySensitivity = new JoystickSens[JoyNumAxes];
591 }
592 }
593
594 if(JoySensitivity)
595 {
596 for(int i = 0;i < JoyNumAxes;++i)
597 {
598 FString settingName;
599 settingName.Format("JoyAxis%dSensitivity", i);
600 config.CreateSetting(settingName, 10);
601 JoySensitivity[i].sensitivity = config.GetSetting(settingName)->GetInteger();
602 settingName.Format("JoyAxis%dDeadzone", i);
603 config.CreateSetting(settingName, 2);
604 JoySensitivity[i].deadzone = config.GetSetting(settingName)->GetInteger();
605 }
606 }
607 }
608
609 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
610
611 IN_GrabMouse();
612
613 // I didn't find a way to ask libSDL whether a mouse is present, yet...
614 MousePresent = true;
615
616 IN_Started = true;
617 }
618
619 ///////////////////////////////////////////////////////////////////////////
620 //
621 // IN_Shutdown() - Shuts down the Input Mgr
622 //
623 ///////////////////////////////////////////////////////////////////////////
624 void
IN_Shutdown(void)625 IN_Shutdown(void)
626 {
627 if (!IN_Started)
628 return;
629
630 if(JoySensitivity)
631 {
632 for(int i = 0;i < JoyNumAxes;++i)
633 {
634 FString settingName;
635 settingName.Format("JoyAxis%dSensitivity", i);
636 config.GetSetting(settingName)->SetValue(JoySensitivity[i].sensitivity);
637 settingName.Format("JoyAxis%dDeadzone", i);
638 config.GetSetting(settingName)->SetValue(JoySensitivity[i].deadzone);
639 }
640 delete[] JoySensitivity;
641 }
642
643 if(Joystick)
644 SDL_JoystickClose(Joystick);
645 #if SDL_VERSION_ATLEAST(2,0,0)
646 if(GameController)
647 SDL_GameControllerClose(GameController);
648 #endif
649
650 IN_Started = false;
651 }
652
653 ///////////////////////////////////////////////////////////////////////////
654 //
655 // IN_ClearKeysDown() - Clears the keyboard array
656 //
657 ///////////////////////////////////////////////////////////////////////////
658 void
IN_ClearKeysDown(void)659 IN_ClearKeysDown(void)
660 {
661 LastScan = sc_None;
662 LastASCII = key_None;
663 memset ((void *) Keyboard,0,sizeof(Keyboard));
664 }
665
666
667 ///////////////////////////////////////////////////////////////////////////
668 //
669 // IN_ReadControl() - Reads the device associated with the specified
670 // player and fills in the control info struct
671 //
672 ///////////////////////////////////////////////////////////////////////////
673 void
IN_ReadControl(int player,ControlInfo * info)674 IN_ReadControl(int player,ControlInfo *info)
675 {
676 word buttons;
677 int dx,dy;
678 Motion mx,my;
679
680 dx = dy = 0;
681 mx = my = motion_None;
682 buttons = 0;
683
684 IN_ProcessEvents();
685
686 if (Keyboard[KbdDefs.upleft])
687 mx = motion_Left,my = motion_Up;
688 else if (Keyboard[KbdDefs.upright])
689 mx = motion_Right,my = motion_Up;
690 else if (Keyboard[KbdDefs.downleft])
691 mx = motion_Left,my = motion_Down;
692 else if (Keyboard[KbdDefs.downright])
693 mx = motion_Right,my = motion_Down;
694
695 if (Keyboard[KbdDefs.up])
696 my = motion_Up;
697 else if (Keyboard[KbdDefs.down])
698 my = motion_Down;
699
700 if (Keyboard[KbdDefs.left])
701 mx = motion_Left;
702 else if (Keyboard[KbdDefs.right])
703 mx = motion_Right;
704
705 if (Keyboard[KbdDefs.button0])
706 buttons += 1 << 0;
707 if (Keyboard[KbdDefs.button1])
708 buttons += 1 << 1;
709
710 dx = mx * 127;
711 dy = my * 127;
712
713 info->x = dx;
714 info->xaxis = mx;
715 info->y = dy;
716 info->yaxis = my;
717 info->button0 = (buttons & (1 << 0)) != 0;
718 info->button1 = (buttons & (1 << 1)) != 0;
719 info->button2 = (buttons & (1 << 2)) != 0;
720 info->button3 = (buttons & (1 << 3)) != 0;
721 info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
722 }
723
724 ///////////////////////////////////////////////////////////////////////////
725 //
726 // IN_WaitForKey() - Waits for a scan code, then clears LastScan and
727 // returns the scan code
728 //
729 ///////////////////////////////////////////////////////////////////////////
730 ScanCode
IN_WaitForKey(void)731 IN_WaitForKey(void)
732 {
733 ScanCode result;
734
735 while ((result = LastScan)==0)
736 IN_WaitAndProcessEvents();
737 LastScan = 0;
738 return(result);
739 }
740
741 ///////////////////////////////////////////////////////////////////////////
742 //
743 // IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
744 // returns the ASCII value
745 //
746 ///////////////////////////////////////////////////////////////////////////
747 char
IN_WaitForASCII(void)748 IN_WaitForASCII(void)
749 {
750 char result;
751
752 while ((result = LastASCII)==0)
753 IN_WaitAndProcessEvents();
754 LastASCII = '\0';
755 return(result);
756 }
757
758 ///////////////////////////////////////////////////////////////////////////
759 //
760 // IN_Ack() - waits for a button or key press. If a button is down, upon
761 // calling, it must be released for it to be recognized
762 //
763 ///////////////////////////////////////////////////////////////////////////
764
765 bool btnstate[NUMBUTTONS];
766
IN_StartAck(void)767 void IN_StartAck(void)
768 {
769 IN_ProcessEvents();
770 //
771 // get initial state of everything
772 //
773 IN_ClearKeysDown();
774 memset(btnstate, 0, sizeof(btnstate));
775
776 int buttons = IN_JoyButtons() << 4;
777
778 if(MousePresent)
779 buttons |= IN_MouseButtons();
780
781 for(int i = 0; i < NUMBUTTONS; i++, buttons >>= 1)
782 if(buttons & 1)
783 btnstate[i] = true;
784 }
785
786
IN_CheckAck(void)787 bool IN_CheckAck (void)
788 {
789 IN_ProcessEvents();
790 //
791 // see if something has been pressed
792 //
793 if(LastScan)
794 return true;
795
796 int buttons = IN_JoyButtons() << 4;
797
798 if(MousePresent)
799 buttons |= IN_MouseButtons();
800
801 for(int i = 0; i < NUMBUTTONS; i++, buttons >>= 1)
802 {
803 if(buttons & 1)
804 {
805 if(!btnstate[i])
806 {
807 // Wait until button has been released
808 do
809 {
810 IN_WaitAndProcessEvents();
811 buttons = IN_JoyButtons() << 4;
812
813 if(MousePresent)
814 buttons |= IN_MouseButtons();
815 }
816 while(buttons & (1 << i));
817
818 return true;
819 }
820 }
821 else
822 btnstate[i] = false;
823 }
824
825 return false;
826 }
827
828
IN_Ack(void)829 void IN_Ack (void)
830 {
831 IN_StartAck ();
832
833 do
834 {
835 IN_WaitAndProcessEvents();
836 }
837 while(!IN_CheckAck ());
838 }
839
840
841 ///////////////////////////////////////////////////////////////////////////
842 //
843 // IN_UserInput() - Waits for the specified delay time (in ticks) or the
844 // user pressing a key or a mouse button. If the clear flag is set, it
845 // then either clears the key or waits for the user to let the mouse
846 // button up.
847 //
848 ///////////////////////////////////////////////////////////////////////////
IN_UserInput(longword delay)849 bool IN_UserInput(longword delay)
850 {
851 longword lasttime;
852
853 lasttime = GetTimeCount();
854 IN_StartAck ();
855 do
856 {
857 IN_ProcessEvents();
858 if (IN_CheckAck())
859 return true;
860 SDL_Delay(5);
861 } while (GetTimeCount() - lasttime < delay);
862 return(false);
863 }
864
865 //===========================================================================
866
867 /*
868 ===================
869 =
870 = IN_MouseButtons
871 =
872 ===================
873 */
IN_MouseButtons(void)874 int IN_MouseButtons (void)
875 {
876 if (MousePresent)
877 return INL_GetMouseButtons();
878 else
879 return 0;
880 }
881
IN_ReleaseMouse()882 void IN_ReleaseMouse()
883 {
884 GrabInput = false;
885 SDL_SetRelativeMouseMode(SDL_FALSE);
886 }
887
IN_GrabMouse()888 void IN_GrabMouse()
889 {
890 if(fullscreen || forcegrabmouse)
891 {
892 GrabInput = true;
893 SDL_SetRelativeMouseMode(SDL_TRUE);
894 }
895 }
896
IN_AdjustMouse()897 void IN_AdjustMouse()
898 {
899 if (mouseenabled && (forcegrabmouse || fullscreen))
900 IN_GrabMouse();
901 else if (!fullscreen)
902 IN_ReleaseMouse();
903 }
904
IN_IsInputGrabbed()905 bool IN_IsInputGrabbed()
906 {
907 return GrabInput;
908 }
909
IN_CenterMouse()910 void IN_CenterMouse()
911 {
912 // Clear out relative mouse movement
913 int x, y;
914 SDL_GetRelativeMouseState(&x, &y);
915 }
916