0,0 → 1,683 |
// |
// ID Engine |
// ID_IN.c - Input Manager |
// v1.0d1 |
// By Jason Blochowiak |
// |
|
// |
// This module handles dealing with the various input devices |
// |
// Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff), |
// User Mgr (for command line parms) |
// |
// Globals: |
// LastScan - The keyboard scan code of the last key pressed |
// LastASCII - The ASCII value of the last key pressed |
// DEBUG - there are more globals |
// |
|
#include "wl_def.h" |
|
|
/* |
============================================================================= |
|
GLOBAL VARIABLES |
|
============================================================================= |
*/ |
|
|
// |
// configuration variables |
// |
boolean MousePresent; |
boolean forcegrabmouse; |
|
|
// Global variables |
volatile boolean Keyboard[SDLK_LAST]; |
volatile boolean Paused; |
volatile char LastASCII; |
volatile ScanCode LastScan; |
|
//KeyboardDef KbdDefs = {0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}; |
static KeyboardDef KbdDefs = { |
sc_Control, // button0 |
sc_Alt, // button1 |
sc_Home, // upleft |
sc_UpArrow, // up |
sc_PgUp, // upright |
sc_LeftArrow, // left |
sc_RightArrow, // right |
sc_End, // downleft |
sc_DownArrow, // down |
sc_PgDn // downright |
}; |
|
static SDL_Joystick *Joystick; |
int JoyNumButtons; |
static int JoyNumHats; |
|
static bool GrabInput = false; |
static bool NeedRestore = false; |
|
/* |
============================================================================= |
|
LOCAL VARIABLES |
|
============================================================================= |
*/ |
byte ASCIINames[] = // Unshifted ASCII for scan codes // TODO: keypad |
{ |
// 0 1 2 3 4 5 6 7 8 9 A B C D E F |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,8 ,9 ,0 ,0 ,0 ,13 ,0 ,0 , // 0 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,27 ,0 ,0 ,0 , // 1 |
' ',0 ,0 ,0 ,0 ,0 ,0 ,39 ,0 ,0 ,'*','+',',','-','.','/', // 2 |
'0','1','2','3','4','5','6','7','8','9',0 ,';',0 ,'=',0 ,0 , // 3 |
'`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o', // 4 |
'p','q','r','s','t','u','v','w','x','y','z','[',92 ,']',0 ,0 , // 5 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 |
}; |
byte ShiftNames[] = // Shifted ASCII for scan codes |
{ |
// 0 1 2 3 4 5 6 7 8 9 A B C D E F |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,8 ,9 ,0 ,0 ,0 ,13 ,0 ,0 , // 0 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,27 ,0 ,0 ,0 , // 1 |
' ',0 ,0 ,0 ,0 ,0 ,0 ,34 ,0 ,0 ,'*','+','<','_','>','?', // 2 |
')','!','@','#','$','%','^','&','*','(',0 ,':',0 ,'+',0 ,0 , // 3 |
'~','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', // 4 |
'P','Q','R','S','T','U','V','W','X','Y','Z','{','|','}',0 ,0 , // 5 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 |
}; |
byte SpecialNames[] = // ASCII for 0xe0 prefixed codes |
{ |
// 0 1 2 3 4 5 6 7 8 9 A B C D E F |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2 |
0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6 |
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7 |
}; |
|
|
static boolean IN_Started; |
|
static Direction DirTable[] = // Quick lookup for total direction |
{ |
dir_NorthWest, dir_North, dir_NorthEast, |
dir_West, dir_None, dir_East, |
dir_SouthWest, dir_South, dir_SouthEast |
}; |
|
|
/////////////////////////////////////////////////////////////////////////// |
// |
// INL_GetMouseButtons() - Gets the status of the mouse buttons from the |
// mouse driver |
// |
/////////////////////////////////////////////////////////////////////////// |
static int |
INL_GetMouseButtons(void) |
{ |
int buttons = SDL_GetMouseState(NULL, NULL); |
int middlePressed = buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE); |
int rightPressed = buttons & SDL_BUTTON(SDL_BUTTON_RIGHT); |
buttons &= ~(SDL_BUTTON(SDL_BUTTON_MIDDLE) | SDL_BUTTON(SDL_BUTTON_RIGHT)); |
if(middlePressed) buttons |= 1 << 2; |
if(rightPressed) buttons |= 1 << 1; |
|
return buttons; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_GetJoyDelta() - Returns the relative movement of the specified |
// joystick (from +/-127) |
// |
/////////////////////////////////////////////////////////////////////////// |
void IN_GetJoyDelta(int *dx,int *dy) |
{ |
if(!Joystick) |
{ |
*dx = *dy = 0; |
return; |
} |
|
SDL_JoystickUpdate(); |
#ifdef _arch_dreamcast |
int x = 0; |
int y = 0; |
#else |
int x = SDL_JoystickGetAxis(Joystick, 0) >> 8; |
int y = SDL_JoystickGetAxis(Joystick, 1) >> 8; |
#endif |
|
if(param_joystickhat != -1) |
{ |
uint8_t hatState = SDL_JoystickGetHat(Joystick, param_joystickhat); |
if(hatState & SDL_HAT_RIGHT) |
x += 127; |
else if(hatState & SDL_HAT_LEFT) |
x -= 127; |
if(hatState & SDL_HAT_DOWN) |
y += 127; |
else if(hatState & SDL_HAT_UP) |
y -= 127; |
|
if(x < -128) x = -128; |
else if(x > 127) x = 127; |
|
if(y < -128) y = -128; |
else if(y > 127) y = 127; |
} |
|
*dx = x; |
*dy = y; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_GetJoyFineDelta() - Returns the relative movement of the specified |
// joystick without dividing the results by 256 (from +/-127) |
// |
/////////////////////////////////////////////////////////////////////////// |
void IN_GetJoyFineDelta(int *dx, int *dy) |
{ |
if(!Joystick) |
{ |
*dx = 0; |
*dy = 0; |
return; |
} |
|
SDL_JoystickUpdate(); |
int x = SDL_JoystickGetAxis(Joystick, 0); |
int y = SDL_JoystickGetAxis(Joystick, 1); |
|
if(x < -128) x = -128; |
else if(x > 127) x = 127; |
|
if(y < -128) y = -128; |
else if(y > 127) y = 127; |
|
*dx = x; |
*dy = y; |
} |
|
/* |
=================== |
= |
= IN_JoyButtons |
= |
=================== |
*/ |
|
int IN_JoyButtons() |
{ |
if(!Joystick) return 0; |
|
SDL_JoystickUpdate(); |
|
int res = 0; |
for(int i = 0; i < JoyNumButtons && i < 32; i++) |
res |= SDL_JoystickGetButton(Joystick, i) << i; |
return res; |
} |
|
boolean IN_JoyPresent() |
{ |
return Joystick != NULL; |
} |
|
static void processEvent(SDL_Event *event) |
{ |
switch (event->type) |
{ |
// exit if the window is closed |
case SDL_QUIT: |
Quit(NULL); |
|
// check for keypresses |
case SDL_KEYDOWN: |
{ |
if(event->key.keysym.sym==SDLK_SCROLLOCK || event->key.keysym.sym==SDLK_F12) |
{ |
GrabInput = !GrabInput; |
SDL_WM_GrabInput(GrabInput ? SDL_GRAB_ON : SDL_GRAB_OFF); |
return; |
} |
|
LastScan = event->key.keysym.sym; |
SDLMod mod = SDL_GetModState(); |
if(Keyboard[sc_Alt]) |
{ |
if(LastScan==SDLK_F4) |
Quit(NULL); |
} |
|
if(LastScan == SDLK_KP_ENTER) LastScan = SDLK_RETURN; |
else if(LastScan == SDLK_RSHIFT) LastScan = SDLK_LSHIFT; |
else if(LastScan == SDLK_RALT) LastScan = SDLK_LALT; |
else if(LastScan == SDLK_RCTRL) LastScan = SDLK_LCTRL; |
else |
{ |
if((mod & KMOD_NUM) == 0) |
{ |
switch(LastScan) |
{ |
case SDLK_KP2: LastScan = SDLK_DOWN; break; |
case SDLK_KP4: LastScan = SDLK_LEFT; break; |
case SDLK_KP6: LastScan = SDLK_RIGHT; break; |
case SDLK_KP8: LastScan = SDLK_UP; break; |
} |
} |
} |
|
int sym = LastScan; |
if(sym >= 'a' && sym <= 'z') |
sym -= 32; // convert to uppercase |
|
if(mod & (KMOD_SHIFT | KMOD_CAPS)) |
{ |
if(sym < lengthof(ShiftNames) && ShiftNames[sym]) |
LastASCII = ShiftNames[sym]; |
} |
else |
{ |
if(sym < lengthof(ASCIINames) && ASCIINames[sym]) |
LastASCII = ASCIINames[sym]; |
} |
if(LastScan<SDLK_LAST) |
Keyboard[LastScan] = 1; |
if(LastScan == SDLK_PAUSE) |
Paused = true; |
break; |
} |
|
case SDL_KEYUP: |
{ |
int key = event->key.keysym.sym; |
if(key == SDLK_KP_ENTER) key = SDLK_RETURN; |
else if(key == SDLK_RSHIFT) key = SDLK_LSHIFT; |
else if(key == SDLK_RALT) key = SDLK_LALT; |
else if(key == SDLK_RCTRL) key = SDLK_LCTRL; |
else |
{ |
if((SDL_GetModState() & KMOD_NUM) == 0) |
{ |
switch(key) |
{ |
case SDLK_KP2: key = SDLK_DOWN; break; |
case SDLK_KP4: key = SDLK_LEFT; break; |
case SDLK_KP6: key = SDLK_RIGHT; break; |
case SDLK_KP8: key = SDLK_UP; break; |
} |
} |
} |
|
if(key<SDLK_LAST) |
Keyboard[key] = 0; |
break; |
} |
|
case SDL_ACTIVEEVENT: |
{ |
if(fullscreen && (event->active.state & SDL_APPACTIVE) != 0) |
{ |
if(event->active.gain) |
{ |
if(NeedRestore) |
{ |
FreeLatchMem(); |
LoadLatchMem(); |
} |
|
NeedRestore = false; |
} |
else NeedRestore = true; |
} |
} |
|
#if defined(GP2X) |
case SDL_JOYBUTTONDOWN: |
GP2X_ButtonDown(event->jbutton.button); |
break; |
|
case SDL_JOYBUTTONUP: |
GP2X_ButtonUp(event->jbutton.button); |
break; |
#endif |
} |
} |
|
void IN_WaitAndProcessEvents() |
{ |
SDL_Event event; |
if(!SDL_WaitEvent(&event)) return; |
do |
{ |
processEvent(&event); |
} |
while(SDL_PollEvent(&event)); |
} |
|
void IN_ProcessEvents() |
{ |
SDL_Event event; |
|
while (SDL_PollEvent(&event)) |
{ |
processEvent(&event); |
} |
} |
|
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_Startup() - Starts up the Input Mgr |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
IN_Startup(void) |
{ |
if (IN_Started) |
return; |
|
IN_ClearKeysDown(); |
|
if(param_joystickindex >= 0 && param_joystickindex < SDL_NumJoysticks()) |
{ |
Joystick = SDL_JoystickOpen(param_joystickindex); |
if(Joystick) |
{ |
JoyNumButtons = SDL_JoystickNumButtons(Joystick); |
if(JoyNumButtons > 32) JoyNumButtons = 32; // only up to 32 buttons are supported |
JoyNumHats = SDL_JoystickNumHats(Joystick); |
if(param_joystickhat < -1 || param_joystickhat >= JoyNumHats) |
Quit("The joystickhat param must be between 0 and %i!", JoyNumHats - 1); |
} |
} |
|
SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); |
|
if(fullscreen || forcegrabmouse) |
{ |
GrabInput = true; |
SDL_WM_GrabInput(SDL_GRAB_ON); |
} |
|
// I didn't find a way to ask libSDL whether a mouse is present, yet... |
#if defined(GP2X) |
MousePresent = false; |
#elif defined(_arch_dreamcast) |
MousePresent = DC_MousePresent(); |
#else |
MousePresent = true; |
#endif |
|
IN_Started = true; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_Shutdown() - Shuts down the Input Mgr |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
IN_Shutdown(void) |
{ |
if (!IN_Started) |
return; |
|
if(Joystick) |
SDL_JoystickClose(Joystick); |
|
IN_Started = false; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_ClearKeysDown() - Clears the keyboard array |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
IN_ClearKeysDown(void) |
{ |
LastScan = sc_None; |
LastASCII = key_None; |
memset ((void *) Keyboard,0,sizeof(Keyboard)); |
} |
|
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_ReadControl() - Reads the device associated with the specified |
// player and fills in the control info struct |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
IN_ReadControl(int player,ControlInfo *info) |
{ |
word buttons; |
int dx,dy; |
Motion mx,my; |
|
dx = dy = 0; |
mx = my = motion_None; |
buttons = 0; |
|
IN_ProcessEvents(); |
|
if (Keyboard[KbdDefs.upleft]) |
mx = motion_Left,my = motion_Up; |
else if (Keyboard[KbdDefs.upright]) |
mx = motion_Right,my = motion_Up; |
else if (Keyboard[KbdDefs.downleft]) |
mx = motion_Left,my = motion_Down; |
else if (Keyboard[KbdDefs.downright]) |
mx = motion_Right,my = motion_Down; |
|
if (Keyboard[KbdDefs.up]) |
my = motion_Up; |
else if (Keyboard[KbdDefs.down]) |
my = motion_Down; |
|
if (Keyboard[KbdDefs.left]) |
mx = motion_Left; |
else if (Keyboard[KbdDefs.right]) |
mx = motion_Right; |
|
if (Keyboard[KbdDefs.button0]) |
buttons += 1 << 0; |
if (Keyboard[KbdDefs.button1]) |
buttons += 1 << 1; |
|
dx = mx * 127; |
dy = my * 127; |
|
info->x = dx; |
info->xaxis = mx; |
info->y = dy; |
info->yaxis = my; |
info->button0 = (buttons & (1 << 0)) != 0; |
info->button1 = (buttons & (1 << 1)) != 0; |
info->button2 = (buttons & (1 << 2)) != 0; |
info->button3 = (buttons & (1 << 3)) != 0; |
info->dir = DirTable[((my + 1) * 3) + (mx + 1)]; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_WaitForKey() - Waits for a scan code, then clears LastScan and |
// returns the scan code |
// |
/////////////////////////////////////////////////////////////////////////// |
ScanCode |
IN_WaitForKey(void) |
{ |
ScanCode result; |
|
while ((result = LastScan)==0) |
IN_WaitAndProcessEvents(); |
LastScan = 0; |
return(result); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and |
// returns the ASCII value |
// |
/////////////////////////////////////////////////////////////////////////// |
char |
IN_WaitForASCII(void) |
{ |
char result; |
|
while ((result = LastASCII)==0) |
IN_WaitAndProcessEvents(); |
LastASCII = '\0'; |
return(result); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_Ack() - waits for a button or key press. If a button is down, upon |
// calling, it must be released for it to be recognized |
// |
/////////////////////////////////////////////////////////////////////////// |
|
boolean btnstate[NUMBUTTONS]; |
|
void IN_StartAck(void) |
{ |
IN_ProcessEvents(); |
// |
// get initial state of everything |
// |
IN_ClearKeysDown(); |
memset(btnstate, 0, sizeof(btnstate)); |
|
int buttons = IN_JoyButtons() << 4; |
|
if(MousePresent) |
buttons |= IN_MouseButtons(); |
|
for(int i = 0; i < NUMBUTTONS; i++, buttons >>= 1) |
if(buttons & 1) |
btnstate[i] = true; |
} |
|
|
boolean IN_CheckAck (void) |
{ |
IN_ProcessEvents(); |
// |
// see if something has been pressed |
// |
if(LastScan) |
return true; |
|
int buttons = IN_JoyButtons() << 4; |
|
if(MousePresent) |
buttons |= IN_MouseButtons(); |
|
for(int i = 0; i < NUMBUTTONS; i++, buttons >>= 1) |
{ |
if(buttons & 1) |
{ |
if(!btnstate[i]) |
{ |
// Wait until button has been released |
do |
{ |
IN_WaitAndProcessEvents(); |
buttons = IN_JoyButtons() << 4; |
|
if(MousePresent) |
buttons |= IN_MouseButtons(); |
} |
while(buttons & (1 << i)); |
|
return true; |
} |
} |
else |
btnstate[i] = false; |
} |
|
return false; |
} |
|
|
void IN_Ack (void) |
{ |
IN_StartAck (); |
|
do |
{ |
IN_WaitAndProcessEvents(); |
} |
while(!IN_CheckAck ()); |
} |
|
|
/////////////////////////////////////////////////////////////////////////// |
// |
// IN_UserInput() - Waits for the specified delay time (in ticks) or the |
// user pressing a key or a mouse button. If the clear flag is set, it |
// then either clears the key or waits for the user to let the mouse |
// button up. |
// |
/////////////////////////////////////////////////////////////////////////// |
boolean IN_UserInput(longword delay) |
{ |
longword lasttime; |
|
lasttime = GetTimeCount(); |
IN_StartAck (); |
do |
{ |
IN_ProcessEvents(); |
if (IN_CheckAck()) |
return true; |
SDL_Delay(5); |
} while (GetTimeCount() - lasttime < delay); |
return(false); |
} |
|
//=========================================================================== |
|
/* |
=================== |
= |
= IN_MouseButtons |
= |
=================== |
*/ |
int IN_MouseButtons (void) |
{ |
if (MousePresent) |
return INL_GetMouseButtons(); |
else |
return 0; |
} |
|
bool IN_IsInputGrabbed() |
{ |
return GrabInput; |
} |
|
void IN_CenterMouse() |
{ |
SDL_WarpMouse(screenWidth / 2, screenHeight / 2); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |