📄 cl_input.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// cl.input.c -- builds an intended movement command to send to the server
#include "client.h"
unsigned frame_msec;
int old_com_frameTime;
/*
===============================================================================
KEY BUTTONS
Continuous button event tracking is complicated by the fact that two different
input sources (say, mouse button 1 and the control key) can both press the
same button, but the button should only be released when both of the
pressing key have been released.
When a key event issues a button command (+forward, +attack, etc), it appends
its key number as argv(1) so it can be matched up with the release.
argv(2) will be set to the time the event happened, which allows exact
control even at low framerates when the down and up events may both get qued
at the same time.
===============================================================================
*/
kbutton_t in_left, in_right, in_forward, in_back;
kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright;
kbutton_t in_strafe, in_speed;
kbutton_t in_up, in_down;
kbutton_t in_buttons[16];
qboolean in_mlooking;
void IN_MLookDown( void ) {
in_mlooking = qtrue;
}
void IN_MLookUp( void ) {
in_mlooking = qfalse;
if ( !cl_freelook->integer ) {
IN_CenterView ();
}
}
void IN_KeyDown( kbutton_t *b ) {
int k;
char *c;
c = Cmd_Argv(1);
if ( c[0] ) {
k = atoi(c);
} else {
k = -1; // typed manually at the console for continuous down
}
if ( k == b->down[0] || k == b->down[1] ) {
return; // repeating key
}
if ( !b->down[0] ) {
b->down[0] = k;
} else if ( !b->down[1] ) {
b->down[1] = k;
} else {
Com_Printf ("Three keys down for a button!\n");
return;
}
if ( b->active ) {
return; // still down
}
// save timestamp for partial frame summing
c = Cmd_Argv(2);
b->downtime = atoi(c);
b->active = qtrue;
b->wasPressed = qtrue;
}
void IN_KeyUp( kbutton_t *b ) {
int k;
char *c;
unsigned uptime;
c = Cmd_Argv(1);
if ( c[0] ) {
k = atoi(c);
} else {
// typed manually at the console, assume for unsticking, so clear all
b->down[0] = b->down[1] = 0;
b->active = qfalse;
return;
}
if ( b->down[0] == k ) {
b->down[0] = 0;
} else if ( b->down[1] == k ) {
b->down[1] = 0;
} else {
return; // key up without coresponding down (menu pass through)
}
if ( b->down[0] || b->down[1] ) {
return; // some other key is still holding it down
}
b->active = qfalse;
// save timestamp for partial frame summing
c = Cmd_Argv(2);
uptime = atoi(c);
if ( uptime ) {
b->msec += uptime - b->downtime;
} else {
b->msec += frame_msec / 2;
}
b->active = qfalse;
}
/*
===============
CL_KeyState
Returns the fraction of the frame that the key was down
===============
*/
float CL_KeyState( kbutton_t *key ) {
float val;
int msec;
msec = key->msec;
key->msec = 0;
if ( key->active ) {
// still down
if ( !key->downtime ) {
msec = com_frameTime;
} else {
msec += com_frameTime - key->downtime;
}
key->downtime = com_frameTime;
}
#if 0
if (msec) {
Com_Printf ("%i ", msec);
}
#endif
val = (float)msec / frame_msec;
if ( val < 0 ) {
val = 0;
}
if ( val > 1 ) {
val = 1;
}
return val;
}
void IN_UpDown(void) {IN_KeyDown(&in_up);}
void IN_UpUp(void) {IN_KeyUp(&in_up);}
void IN_DownDown(void) {IN_KeyDown(&in_down);}
void IN_DownUp(void) {IN_KeyUp(&in_down);}
void IN_LeftDown(void) {IN_KeyDown(&in_left);}
void IN_LeftUp(void) {IN_KeyUp(&in_left);}
void IN_RightDown(void) {IN_KeyDown(&in_right);}
void IN_RightUp(void) {IN_KeyUp(&in_right);}
void IN_ForwardDown(void) {IN_KeyDown(&in_forward);}
void IN_ForwardUp(void) {IN_KeyUp(&in_forward);}
void IN_BackDown(void) {IN_KeyDown(&in_back);}
void IN_BackUp(void) {IN_KeyUp(&in_back);}
void IN_LookupDown(void) {IN_KeyDown(&in_lookup);}
void IN_LookupUp(void) {IN_KeyUp(&in_lookup);}
void IN_LookdownDown(void) {IN_KeyDown(&in_lookdown);}
void IN_LookdownUp(void) {IN_KeyUp(&in_lookdown);}
void IN_MoveleftDown(void) {IN_KeyDown(&in_moveleft);}
void IN_MoveleftUp(void) {IN_KeyUp(&in_moveleft);}
void IN_MoverightDown(void) {IN_KeyDown(&in_moveright);}
void IN_MoverightUp(void) {IN_KeyUp(&in_moveright);}
void IN_SpeedDown(void) {IN_KeyDown(&in_speed);}
void IN_SpeedUp(void) {IN_KeyUp(&in_speed);}
void IN_StrafeDown(void) {IN_KeyDown(&in_strafe);}
void IN_StrafeUp(void) {IN_KeyUp(&in_strafe);}
void IN_Button0Down(void) {IN_KeyDown(&in_buttons[0]);}
void IN_Button0Up(void) {IN_KeyUp(&in_buttons[0]);}
void IN_Button1Down(void) {IN_KeyDown(&in_buttons[1]);}
void IN_Button1Up(void) {IN_KeyUp(&in_buttons[1]);}
void IN_Button2Down(void) {IN_KeyDown(&in_buttons[2]);}
void IN_Button2Up(void) {IN_KeyUp(&in_buttons[2]);}
void IN_Button3Down(void) {IN_KeyDown(&in_buttons[3]);}
void IN_Button3Up(void) {IN_KeyUp(&in_buttons[3]);}
void IN_Button4Down(void) {IN_KeyDown(&in_buttons[4]);}
void IN_Button4Up(void) {IN_KeyUp(&in_buttons[4]);}
void IN_Button5Down(void) {IN_KeyDown(&in_buttons[5]);}
void IN_Button5Up(void) {IN_KeyUp(&in_buttons[5]);}
void IN_Button6Down(void) {IN_KeyDown(&in_buttons[6]);}
void IN_Button6Up(void) {IN_KeyUp(&in_buttons[6]);}
void IN_Button7Down(void) {IN_KeyDown(&in_buttons[7]);}
void IN_Button7Up(void) {IN_KeyUp(&in_buttons[7]);}
void IN_Button8Down(void) {IN_KeyDown(&in_buttons[8]);}
void IN_Button8Up(void) {IN_KeyUp(&in_buttons[8]);}
void IN_Button9Down(void) {IN_KeyDown(&in_buttons[9]);}
void IN_Button9Up(void) {IN_KeyUp(&in_buttons[9]);}
void IN_Button10Down(void) {IN_KeyDown(&in_buttons[10]);}
void IN_Button10Up(void) {IN_KeyUp(&in_buttons[10]);}
void IN_Button11Down(void) {IN_KeyDown(&in_buttons[11]);}
void IN_Button11Up(void) {IN_KeyUp(&in_buttons[11]);}
void IN_Button12Down(void) {IN_KeyDown(&in_buttons[12]);}
void IN_Button12Up(void) {IN_KeyUp(&in_buttons[12]);}
void IN_Button13Down(void) {IN_KeyDown(&in_buttons[13]);}
void IN_Button13Up(void) {IN_KeyUp(&in_buttons[13]);}
void IN_Button14Down(void) {IN_KeyDown(&in_buttons[14]);}
void IN_Button14Up(void) {IN_KeyUp(&in_buttons[14]);}
void IN_Button15Down(void) {IN_KeyDown(&in_buttons[15]);}
void IN_Button15Up(void) {IN_KeyUp(&in_buttons[15]);}
void IN_ButtonDown (void) {
IN_KeyDown(&in_buttons[1]);}
void IN_ButtonUp (void) {
IN_KeyUp(&in_buttons[1]);}
void IN_CenterView (void) {
cl.viewangles[PITCH] = -SHORT2ANGLE(cl.snap.ps.delta_angles[PITCH]);
}
//==========================================================================
cvar_t *cl_upspeed;
cvar_t *cl_forwardspeed;
cvar_t *cl_sidespeed;
cvar_t *cl_yawspeed;
cvar_t *cl_pitchspeed;
cvar_t *cl_run;
cvar_t *cl_anglespeedkey;
/*
================
CL_AdjustAngles
Moves the local angle positions
================
*/
void CL_AdjustAngles( void ) {
float speed;
if ( in_speed.active ) {
speed = 0.001 * cls.frametime * cl_anglespeedkey->value;
} else {
speed = 0.001 * cls.frametime;
}
if ( !in_strafe.active ) {
cl.viewangles[YAW] -= speed*cl_yawspeed->value*CL_KeyState (&in_right);
cl.viewangles[YAW] += speed*cl_yawspeed->value*CL_KeyState (&in_left);
}
cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * CL_KeyState (&in_lookup);
cl.viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_lookdown);
}
/*
================
CL_KeyMove
Sets the usercmd_t based on key states
================
*/
void CL_KeyMove( usercmd_t *cmd ) {
int movespeed;
int forward, side, up;
//
// adjust for speed key / running
// the walking flag is to keep animations consistant
// even during acceleration and develeration
//
if ( in_speed.active ^ cl_run->integer ) {
movespeed = 127;
cmd->buttons &= ~BUTTON_WALKING;
} else {
cmd->buttons |= BUTTON_WALKING;
movespeed = 64;
}
forward = 0;
side = 0;
up = 0;
if ( in_strafe.active ) {
side += movespeed * CL_KeyState (&in_right);
side -= movespeed * CL_KeyState (&in_left);
}
side += movespeed * CL_KeyState (&in_moveright);
side -= movespeed * CL_KeyState (&in_moveleft);
up += movespeed * CL_KeyState (&in_up);
up -= movespeed * CL_KeyState (&in_down);
forward += movespeed * CL_KeyState (&in_forward);
forward -= movespeed * CL_KeyState (&in_back);
cmd->forwardmove = ClampChar( forward );
cmd->rightmove = ClampChar( side );
cmd->upmove = ClampChar( up );
}
/*
=================
CL_MouseEvent
=================
*/
void CL_MouseEvent( int dx, int dy, int time ) {
if ( cls.keyCatchers & KEYCATCH_UI ) {
VM_Call( uivm, UI_MOUSE_EVENT, dx, dy );
} else if (cls.keyCatchers & KEYCATCH_CGAME) {
VM_Call (cgvm, CG_MOUSE_EVENT, dx, dy);
} else {
cl.mouseDx[cl.mouseIndex] += dx;
cl.mouseDy[cl.mouseIndex] += dy;
}
}
/*
=================
CL_JoystickEvent
Joystick values stay set until changed
=================
*/
void CL_JoystickEvent( int axis, int value, int time ) {
if ( axis < 0 || axis >= MAX_JOYSTICK_AXIS ) {
Com_Error( ERR_DROP, "CL_JoystickEvent: bad axis %i", axis );
}
cl.joystickAxis[axis] = value;
}
/*
=================
CL_JoystickMove
=================
*/
void CL_JoystickMove( usercmd_t *cmd ) {
int movespeed;
float anglespeed;
if ( in_speed.active ^ cl_run->integer ) {
movespeed = 2;
} else {
movespeed = 1;
cmd->buttons |= BUTTON_WALKING;
}
if ( in_speed.active ) {
anglespeed = 0.001 * cls.frametime * cl_anglespeedkey->value;
} else {
anglespeed = 0.001 * cls.frametime;
}
if ( !in_strafe.active ) {
cl.viewangles[YAW] += anglespeed * cl_yawspeed->value * cl.joystickAxis[AXIS_SIDE];
} else {
cmd->rightmove = ClampChar( cmd->rightmove + cl.joystickAxis[AXIS_SIDE] );
}
if ( in_mlooking ) {
cl.viewangles[PITCH] += anglespeed * cl_pitchspeed->value * cl.joystickAxis[AXIS_FORWARD];
} else {
cmd->forwardmove = ClampChar( cmd->forwardmove + cl.joystickAxis[AXIS_FORWARD] );
}
cmd->upmove = ClampChar( cmd->upmove + cl.joystickAxis[AXIS_UP] );
}
/*
=================
CL_MouseMove
=================
*/
void CL_MouseMove( usercmd_t *cmd ) {
float mx, my;
float accelSensitivity;
float rate;
// allow mouse smoothing
if ( m_filter->integer ) {
mx = ( cl.mouseDx[0] + cl.mouseDx[1] ) * 0.5;
my = ( cl.mouseDy[0] + cl.mouseDy[1] ) * 0.5;
} else {
mx = cl.mouseDx[cl.mouseIndex];
my = cl.mouseDy[cl.mouseIndex];
}
cl.mouseIndex ^= 1;
cl.mouseDx[cl.mouseIndex] = 0;
cl.mouseDy[cl.mouseIndex] = 0;
rate = sqrt( mx * mx + my * my ) / (float)frame_msec;
accelSensitivity = cl_sensitivity->value + rate * cl_mouseAccel->value;
// scale by FOV
accelSensitivity *= cl.cgameSensitivity;
if ( rate && cl_showMouseRate->integer ) {
Com_Printf( "%f : %f\n", rate, accelSensitivity );
}
mx *= accelSensitivity;
my *= accelSensitivity;
if (!mx && !my) {
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -