yquake2remaster/src/backends/sdl/input.c

757 lines
14 KiB
C
Raw Normal View History

/*
* Copyright (C) 2010 Yamagi Burmeister
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* This is the Quake II input system, written in SDL.
*
* =======================================================================
*/
#include "../../client/refresh/header/local.h"
2012-08-01 11:47:32 +00:00
#include "../../client/header/keyboard.h"
2012-08-01 14:53:40 +00:00
#include "../generic/header/input.h"
#ifdef _WIN32
#include <SDL/SDL.h>
#elif defined(__APPLE__)
#include <SDL/SDL.h>
#else
#include <SDL.h>
2012-06-11 08:18:44 +00:00
#endif
#define MOUSE_MAX 3000
#define MOUSE_MIN 40
2013-07-30 18:13:49 +00:00
static qboolean have_grab;
2012-06-08 10:23:01 +00:00
static cvar_t *windowed_mouse;
static cvar_t *in_grab;
static int mouse_x, mouse_y;
static int old_mouse_x, old_mouse_y;
static int mouse_buttonstate;
static int mouse_oldbuttonstate;
struct
{
2012-06-08 10:23:01 +00:00
int key;
int down;
} keyq[128];
2012-06-08 10:23:01 +00:00
int keyq_head = 0;
int keyq_tail = 0;
int mx;
2012-04-29 13:57:33 +00:00
int my;
Key_Event_fp_t Key_Event_fp;
2012-06-08 10:23:01 +00:00
extern SDL_Surface *surface;
static in_state_t *in_state;
static unsigned char KeyStates[SDLK_LAST];
2012-06-08 10:23:01 +00:00
static qboolean mlooking;
static cvar_t *sensitivity;
static cvar_t *exponential_speedup;
static cvar_t *lookstrafe;
static cvar_t *m_side;
static cvar_t *m_yaw;
static cvar_t *m_pitch;
static cvar_t *m_forward;
static cvar_t *freelook;
static cvar_t *m_filter;
static cvar_t *in_mouse;
2012-11-13 21:37:17 +00:00
cvar_t *vid_fullscreen;
/*
* This function translates the SDL keycodes
* to the internal key representation of the
* id Tech 2 engine.
*/
int
IN_TranslateSDLtoQ2Key(unsigned int keysym)
{
2012-06-08 10:23:01 +00:00
int key = 0;
if ((keysym >= SDLK_SPACE) && (keysym < SDLK_DELETE))
{
/* These happen to match
2012-06-08 10:23:01 +00:00
the ASCII chars */
key = (int)keysym;
}
else
{
switch (keysym)
{
case SDLK_PAGEUP:
key = K_PGUP;
break;
case SDLK_KP9:
key = K_KP_PGUP;
break;
case SDLK_PAGEDOWN:
key = K_PGDN;
break;
case SDLK_KP3:
key = K_KP_PGDN;
break;
case SDLK_KP7:
key = K_KP_HOME;
break;
case SDLK_HOME:
key = K_HOME;
break;
case SDLK_KP1:
key = K_KP_END;
break;
case SDLK_END:
key = K_END;
break;
case SDLK_KP4:
key = K_KP_LEFTARROW;
break;
case SDLK_LEFT:
key = K_LEFTARROW;
break;
case SDLK_KP6:
key = K_KP_RIGHTARROW;
break;
case SDLK_RIGHT:
key = K_RIGHTARROW;
break;
case SDLK_KP2:
key = K_KP_DOWNARROW;
break;
case SDLK_DOWN:
key = K_DOWNARROW;
break;
case SDLK_KP8:
key = K_KP_UPARROW;
break;
case SDLK_UP:
key = K_UPARROW;
break;
case SDLK_ESCAPE:
key = K_ESCAPE;
2012-06-08 10:23:01 +00:00
break;
case SDLK_KP_ENTER:
key = K_KP_ENTER;
break;
case SDLK_RETURN:
key = K_ENTER;
break;
case SDLK_TAB:
key = K_TAB;
break;
case SDLK_F1:
key = K_F1;
break;
case SDLK_F2:
key = K_F2;
break;
case SDLK_F3:
key = K_F3;
break;
case SDLK_F4:
key = K_F4;
break;
case SDLK_F5:
key = K_F5;
break;
case SDLK_F6:
key = K_F6;
break;
case SDLK_F7:
key = K_F7;
break;
case SDLK_F8:
key = K_F8;
break;
case SDLK_F9:
key = K_F9;
break;
case SDLK_F10:
key = K_F10;
break;
case SDLK_F11:
key = K_F11;
break;
case SDLK_F12:
key = K_F12;
break;
case SDLK_F13:
key = K_F13;
break;
case SDLK_F14:
key = K_F14;
break;
case SDLK_F15:
key = K_F15;
break;
case SDLK_BACKSPACE:
key = K_BACKSPACE;
break;
case SDLK_KP_PERIOD:
key = K_KP_DEL;
break;
case SDLK_DELETE:
key = K_DEL;
break;
case SDLK_PAUSE:
key = K_PAUSE;
break;
case SDLK_LSHIFT:
case SDLK_RSHIFT:
key = K_SHIFT;
break;
case SDLK_LCTRL:
case SDLK_RCTRL:
key = K_CTRL;
break;
case SDLK_RMETA:
case SDLK_LMETA:
key = K_COMMAND;
break;
case SDLK_RALT:
case SDLK_LALT:
key = K_ALT;
break;
case SDLK_LSUPER:
case SDLK_RSUPER:
key = K_SUPER;
break;
case SDLK_KP5:
key = K_KP_5;
break;
case SDLK_INSERT:
key = K_INS;
break;
case SDLK_KP0:
key = K_KP_INS;
break;
case SDLK_KP_MULTIPLY:
key = K_KP_STAR;
break;
case SDLK_KP_PLUS:
key = K_KP_PLUS;
break;
case SDLK_KP_MINUS:
key = K_KP_MINUS;
break;
case SDLK_KP_DIVIDE:
key = K_KP_SLASH;
break;
case SDLK_MODE:
key = K_MODE;
break;
case SDLK_COMPOSE:
key = K_COMPOSE;
break;
case SDLK_HELP:
key = K_HELP;
break;
case SDLK_PRINT:
key = K_PRINT;
break;
case SDLK_SYSREQ:
key = K_SYSREQ;
break;
case SDLK_BREAK:
key = K_BREAK;
break;
case SDLK_MENU:
key = K_MENU;
break;
case SDLK_POWER:
key = K_POWER;
break;
case SDLK_EURO:
key = K_EURO;
break;
case SDLK_UNDO:
key = K_UNDO;
break;
case SDLK_SCROLLOCK:
key = K_SCROLLOCK;
break;
case SDLK_NUMLOCK:
key = K_KP_NUMLOCK;
break;
case SDLK_CAPSLOCK:
key = K_CAPSLOCK;
break;
default:
if ((keysym >= SDLK_WORLD_0) && (keysym <= SDLK_WORLD_95))
{
key = (keysym - SDLK_WORLD_0) + K_WORLD_0;
}
break;
}
}
return key;
}
/*
* Input event processing
*/
2012-04-29 13:57:33 +00:00
void
IN_GetEvent(SDL_Event *event)
{
unsigned int key;
2012-04-29 13:57:33 +00:00
2012-06-08 10:23:01 +00:00
switch (event->type)
{
/* The mouse wheel */
case SDL_MOUSEBUTTONDOWN:
2012-06-08 10:23:01 +00:00
2012-04-29 13:57:33 +00:00
if (event->button.button == 4)
{
keyq[keyq_head].key = K_MWHEELUP;
keyq[keyq_head].down = true;
keyq_head = (keyq_head + 1) & 127;
keyq[keyq_head].key = K_MWHEELUP;
keyq[keyq_head].down = false;
keyq_head = (keyq_head + 1) & 127;
2012-04-29 13:57:33 +00:00
}
else if (event->button.button == 5)
{
keyq[keyq_head].key = K_MWHEELDOWN;
keyq[keyq_head].down = true;
keyq_head = (keyq_head + 1) & 127;
keyq[keyq_head].key = K_MWHEELDOWN;
keyq[keyq_head].down = false;
keyq_head = (keyq_head + 1) & 127;
2012-04-29 13:57:33 +00:00
}
2012-06-08 10:23:01 +00:00
break;
2010-11-18 15:46:25 +00:00
case SDL_MOUSEBUTTONUP:
break;
/* The user pressed a button */
case SDL_KEYDOWN:
2012-06-08 10:23:01 +00:00
/* Fullscreen switch via Alt-Return */
2012-06-08 10:23:01 +00:00
if ((KeyStates[SDLK_LALT] ||
KeyStates[SDLK_RALT]) &&
2012-06-08 10:23:01 +00:00
(event->key.keysym.sym == SDLK_RETURN))
{
SDL_WM_ToggleFullScreen(surface);
2012-04-29 13:57:33 +00:00
if (surface->flags & SDL_FULLSCREEN)
{
Cvar_SetValue("vid_fullscreen", 1);
2012-04-29 13:57:33 +00:00
}
else
{
Cvar_SetValue("vid_fullscreen", 0);
}
2012-11-13 21:37:17 +00:00
vid_fullscreen->modified = false;
break;
}
2012-04-29 13:57:33 +00:00
/* Make Shift+Escape toggle the console. This
really belongs in Key_Event(), but since
Key_ClearStates() can mess up the internal
K_SHIFT state let's do it here instead. */
if ((KeyStates[SDLK_LSHIFT] ||
KeyStates[SDLK_RSHIFT]) &&
(event->key.keysym.sym == SDLK_ESCAPE))
{
Cbuf_ExecuteText(EXEC_NOW, "toggleconsole");
break;
}
KeyStates[event->key.keysym.sym] = 1;
2012-04-29 13:57:33 +00:00
/* Get the pressed key and add it to the key list */
key = IN_TranslateSDLtoQ2Key(event->key.keysym.sym);
2012-06-08 10:23:01 +00:00
2012-04-29 13:57:33 +00:00
if (key)
{
keyq[keyq_head].key = key;
keyq[keyq_head].down = true;
keyq_head = (keyq_head + 1) & 127;
}
2012-06-08 10:23:01 +00:00
break;
2010-10-19 08:30:02 +00:00
/* The user released a key */
case SDL_KEYUP:
2012-06-08 10:23:01 +00:00
2012-04-29 13:57:33 +00:00
if (KeyStates[event->key.keysym.sym])
{
KeyStates[event->key.keysym.sym] = 0;
/* Get the pressed key and remove it from the key list */
key = IN_TranslateSDLtoQ2Key(event->key.keysym.sym);
2012-06-08 10:23:01 +00:00
2012-04-29 13:57:33 +00:00
if (key)
{
keyq[keyq_head].key = key;
keyq[keyq_head].down = false;
keyq_head = (keyq_head + 1) & 127;
}
}
2012-06-08 10:23:01 +00:00
break;
}
}
/*
* Updates the state of the input queue
*/
2012-06-08 10:23:01 +00:00
void
IN_Update(void)
{
2012-06-08 10:23:01 +00:00
SDL_Event event;
static int IN_Update_Flag;
int bstate;
2013-07-30 18:13:49 +00:00
qboolean want_grab;
2012-06-08 10:23:01 +00:00
/* Protection against multiple calls */
if (IN_Update_Flag == 1)
{
return;
}
IN_Update_Flag = 1;
while (SDL_PollEvent(&event))
{
IN_GetEvent(&event);
}
/* Mouse button processing. Button 4
and 5 are the mousewheel and thus
not processed here. */
if (!mx && !my)
{
SDL_GetRelativeMouseState(&mx, &my);
}
mouse_buttonstate = 0;
bstate = SDL_GetMouseState(NULL, NULL);
if (SDL_BUTTON(1) & bstate)
{
mouse_buttonstate |= (1 << 0);
}
if (SDL_BUTTON(3) & bstate)
{
mouse_buttonstate |= (1 << 1);
}
if (SDL_BUTTON(2) & bstate)
{
mouse_buttonstate |= (1 << 2);
}
if (SDL_BUTTON(6) & bstate)
{
mouse_buttonstate |= (1 << 3);
}
if (SDL_BUTTON(7) & bstate)
{
mouse_buttonstate |= (1 << 4);
}
/* Grab and ungrab the mouse if the
* console or the menu is opened */
2013-07-30 18:13:49 +00:00
want_grab = (vid_fullscreen->value || in_grab->value == 1 ||
(in_grab->value == 2 && windowed_mouse->value));
if (have_grab != want_grab)
2012-06-08 10:23:01 +00:00
{
2013-07-30 18:13:49 +00:00
SDL_WM_GrabInput((want_grab ? SDL_GRAB_ON : SDL_GRAB_OFF));
have_grab = want_grab;
2012-06-08 10:23:01 +00:00
}
/* Process the key events */
while (keyq_head != keyq_tail)
{
in_state->Key_Event_fp(keyq[keyq_tail].key, keyq[keyq_tail].down);
keyq_tail = (keyq_tail + 1) & 127;
}
IN_Update_Flag = 0;
}
2012-04-29 13:57:33 +00:00
/*
* Closes all inputs and clears
* the input queue.
*/
2012-06-08 10:23:01 +00:00
void
IN_Close(void)
{
keyq_head = 0;
keyq_tail = 0;
2012-04-29 13:57:33 +00:00
memset(keyq, 0, sizeof(keyq));
}
/*
* Gets the mouse state
*/
2012-06-08 10:23:01 +00:00
void
IN_GetMouseState(int *x, int *y, int *state)
{
*x = mx;
*y = my;
*state = mouse_buttonstate;
2012-04-29 13:57:33 +00:00
}
/*
* Cleares the mouse state
*/
2012-06-08 10:23:01 +00:00
void
IN_ClearMouseState()
{
2012-06-08 10:23:01 +00:00
mx = my = 0;
}
2012-04-29 13:57:33 +00:00
/*
* Centers the view
*/
static void
2012-06-08 10:23:01 +00:00
IN_ForceCenterView(void)
{
2012-06-08 10:23:01 +00:00
in_state->viewangles[PITCH] = 0;
2012-04-29 13:57:33 +00:00
}
/*
* Look up
*/
static void
2012-06-08 10:23:01 +00:00
IN_MLookDown(void)
{
mlooking = true;
}
/*
* Look down
*/
static void
2012-06-08 10:23:01 +00:00
IN_MLookUp(void)
{
mlooking = false;
in_state->IN_CenterView_fp();
}
/*
* Keyboard initialisation. Called by the client.
*/
void
IN_KeyboardInit(Key_Event_fp_t fp)
{
Key_Event_fp = fp;
/* SDL stuff. Moved here from IN_BackendInit because
* this must be done after video is initialized. */
SDL_EnableUNICODE(0);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
2013-07-30 18:13:49 +00:00
have_grab = (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON);
}
/*
* Initializes the backend
*/
void
2012-06-08 10:23:01 +00:00
IN_BackendInit(in_state_t *in_state_p)
{
in_state = in_state_p;
m_filter = Cvar_Get("m_filter", "0", CVAR_ARCHIVE);
in_mouse = Cvar_Get("in_mouse", "0", CVAR_ARCHIVE);
freelook = Cvar_Get("freelook", "1", 0);
lookstrafe = Cvar_Get("lookstrafe", "0", 0);
sensitivity = Cvar_Get("sensitivity", "3", 0);
exponential_speedup = Cvar_Get("exponential_speedup", "0", CVAR_ARCHIVE);
m_pitch = Cvar_Get("m_pitch", "0.022", 0);
m_yaw = Cvar_Get("m_yaw", "0.022", 0);
m_forward = Cvar_Get("m_forward", "1", 0);
m_side = Cvar_Get("m_side", "0.8", 0);
Cmd_AddCommand("+mlook", IN_MLookDown);
Cmd_AddCommand("-mlook", IN_MLookUp);
Cmd_AddCommand("force_centerview", IN_ForceCenterView);
mouse_x = mouse_y = 0.0;
windowed_mouse = Cvar_Get("windowed_mouse", "1",
2012-06-08 10:23:01 +00:00
CVAR_USERINFO | CVAR_ARCHIVE);
in_grab = Cvar_Get("in_grab", "2", CVAR_ARCHIVE);
vid_fullscreen = Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
2012-11-13 21:37:17 +00:00
VID_Printf(PRINT_ALL, "Input initialized.\n");
}
/*
* Shuts the backend down
*/
void
2012-06-08 10:23:01 +00:00
IN_BackendShutdown(void)
{
Cmd_RemoveCommand("+mlook");
Cmd_RemoveCommand("-mlook");
Cmd_RemoveCommand("force_centerview");
VID_Printf(PRINT_ALL, "Input shut down.\n");
}
2010-10-19 08:44:12 +00:00
/*
* Mouse button handling
*/
void
2012-06-08 10:23:01 +00:00
IN_BackendMouseButtons(void)
{
int i;
2012-06-08 10:23:01 +00:00
IN_GetMouseState(&mouse_x, &mouse_y, &mouse_buttonstate);
2012-06-08 10:23:01 +00:00
for (i = 0; i < 3; i++)
2010-10-19 08:30:02 +00:00
{
2012-06-08 10:23:01 +00:00
if ((mouse_buttonstate & (1 << i)) && !(mouse_oldbuttonstate & (1 << i)))
{
2012-06-08 10:23:01 +00:00
in_state->Key_Event_fp(K_MOUSE1 + i, true);
}
2012-06-08 10:23:01 +00:00
if (!(mouse_buttonstate & (1 << i)) && (mouse_oldbuttonstate & (1 << i)))
{
2012-06-08 10:23:01 +00:00
in_state->Key_Event_fp(K_MOUSE1 + i, false);
}
2010-10-19 08:30:02 +00:00
}
2012-06-08 10:23:01 +00:00
if ((mouse_buttonstate & (1 << 3)) && !(mouse_oldbuttonstate & (1 << 3)))
2010-10-19 08:30:02 +00:00
{
2012-06-08 10:23:01 +00:00
in_state->Key_Event_fp(K_MOUSE4, true);
2010-10-19 08:30:02 +00:00
}
2012-06-08 10:23:01 +00:00
if (!(mouse_buttonstate & (1 << 3)) && (mouse_oldbuttonstate & (1 << 3)))
2010-10-19 08:30:02 +00:00
{
2012-06-08 10:23:01 +00:00
in_state->Key_Event_fp(K_MOUSE4, false);
2010-10-19 08:30:02 +00:00
}
2012-06-08 10:23:01 +00:00
if ((mouse_buttonstate & (1 << 4)) && !(mouse_oldbuttonstate & (1 << 4)))
2010-10-19 08:30:02 +00:00
{
2012-06-08 10:23:01 +00:00
in_state->Key_Event_fp(K_MOUSE5, true);
2010-10-19 08:30:02 +00:00
}
2012-06-08 10:23:01 +00:00
if (!(mouse_buttonstate & (1 << 4)) && (mouse_oldbuttonstate & (1 << 4)))
2010-10-19 08:30:02 +00:00
{
2012-06-08 10:23:01 +00:00
in_state->Key_Event_fp(K_MOUSE5, false);
}
2010-10-19 08:30:02 +00:00
mouse_oldbuttonstate = mouse_buttonstate;
}
2010-10-19 08:44:12 +00:00
/*
* Move handling
*/
void
2012-06-08 10:23:01 +00:00
IN_BackendMove(usercmd_t *cmd)
{
2012-06-08 10:23:01 +00:00
IN_GetMouseState(&mouse_x, &mouse_y, &mouse_buttonstate);
2012-04-29 13:57:33 +00:00
2012-06-08 10:23:01 +00:00
if (m_filter->value)
{
2012-06-08 10:23:01 +00:00
if ((mouse_x > 1) || (mouse_x < -1))
2010-10-23 10:55:53 +00:00
{
2012-06-08 10:23:01 +00:00
mouse_x = (mouse_x + old_mouse_x) * 0.5;
2010-10-23 10:55:53 +00:00
}
2012-06-08 10:23:01 +00:00
if ((mouse_y > 1) || (mouse_y < -1))
2010-10-23 10:55:53 +00:00
{
2012-06-08 10:23:01 +00:00
mouse_y = (mouse_y + old_mouse_y) * 0.5;
2010-10-23 10:55:53 +00:00
}
2010-10-19 08:30:02 +00:00
}
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;
2012-06-08 10:23:01 +00:00
if (mouse_x || mouse_y)
2010-10-19 08:30:02 +00:00
{
2012-06-08 10:23:01 +00:00
if (!exponential_speedup->value)
{
2010-10-19 08:30:02 +00:00
mouse_x *= sensitivity->value;
mouse_y *= sensitivity->value;
}
2010-10-19 08:30:02 +00:00
else
{
2012-06-08 10:23:01 +00:00
if ((mouse_x > MOUSE_MIN) || (mouse_y > MOUSE_MIN) ||
(mouse_x < -MOUSE_MIN) || (mouse_y < -MOUSE_MIN))
{
2012-06-08 10:23:01 +00:00
mouse_x = (mouse_x * mouse_x * mouse_x) / 4;
mouse_y = (mouse_y * mouse_y * mouse_y) / 4;
2010-10-19 08:30:02 +00:00
2012-06-08 10:23:01 +00:00
if (mouse_x > MOUSE_MAX)
{
2010-10-19 08:30:02 +00:00
mouse_x = MOUSE_MAX;
}
2012-06-08 10:23:01 +00:00
else if (mouse_x < -MOUSE_MAX)
2010-10-19 08:30:02 +00:00
{
mouse_x = -MOUSE_MAX;
}
2012-06-08 10:23:01 +00:00
if (mouse_y > MOUSE_MAX)
2010-10-19 08:30:02 +00:00
{
mouse_y = MOUSE_MAX;
}
2012-06-08 10:23:01 +00:00
else if (mouse_y < -MOUSE_MAX)
2010-10-19 08:30:02 +00:00
{
mouse_y = -MOUSE_MAX;
}
}
2010-10-19 08:30:02 +00:00
}
2010-10-19 08:30:02 +00:00
/* add mouse X/Y movement to cmd */
2012-06-08 10:23:01 +00:00
if ((*in_state->in_strafe_state & 1) ||
(lookstrafe->value && mlooking))
2010-10-19 08:30:02 +00:00
{
cmd->sidemove += m_side->value * mouse_x;
}
else
{
2012-06-08 10:23:01 +00:00
in_state->viewangles[YAW] -= m_yaw->value * mouse_x;
2010-10-19 08:30:02 +00:00
}
2012-06-08 10:23:01 +00:00
if ((mlooking || freelook->value) &&
!(*in_state->in_strafe_state & 1))
2010-10-19 08:30:02 +00:00
{
2012-06-08 10:23:01 +00:00
in_state->viewangles[PITCH] += m_pitch->value * mouse_y;
}
2010-10-19 08:30:02 +00:00
else
{
cmd->forwardmove -= m_forward->value * mouse_y;
}
IN_ClearMouseState();
}
}
2012-06-08 10:23:01 +00:00