Rewrite of key event processing, thanks to /dev/humancontroller and Ben Millwood. https://bugzilla.icculus.org/show_bug.cgi?id=3374

This commit is contained in:
Thilo Schulz 2009-10-03 23:35:07 +00:00
parent 3a952ff196
commit dd572db7d6
1 changed files with 103 additions and 136 deletions

View File

@ -1118,94 +1118,72 @@ void CL_InitKeyCommands( void ) {
/*
===================
CL_AddKeyUpCommands
CL_ParseBinding
Execute the commands in the bind string
===================
*/
void CL_AddKeyUpCommands( int key, char *kb, unsigned time) {
int i;
char button[1024], *buttonPtr;
char cmd[1024];
qboolean keyevent;
void CL_ParseBinding( int key, qboolean down, unsigned time )
{
char buf[ MAX_STRING_CHARS ], *p = buf, *end;
if ( !kb ) {
if( !keys[key].binding || !keys[key].binding[0] )
return;
}
keyevent = qfalse;
buttonPtr = button;
for ( i = 0; ; i++ ) {
if ( kb[i] == ';' || !kb[i] ) {
*buttonPtr = '\0';
if ( button[0] == '+') {
// button commands add keynum and time as parms so that multiple
// sources can be discriminated and subframe corrected
Com_sprintf (cmd, sizeof(cmd), "-%s %i %i\n", button+1, key, time);
Cbuf_AddText (cmd);
keyevent = qtrue;
} else {
if (keyevent) {
// down-only command
Cbuf_AddText (button);
Cbuf_AddText ("\n");
}
}
buttonPtr = button;
while ( (kb[i] <= ' ' || kb[i] == ';') && kb[i] != 0 ) {
i++;
}
Q_strncpyz( buf, keys[key].binding, sizeof( buf ) );
while( 1 )
{
while( isspace( *p ) )
p++;
end = strchr( p, ';' );
if( end )
*end = '\0';
if( *p == '+' )
{
// button commands add keynum and time as parameters
// so that multiple sources can be discriminated and
// subframe corrected
char cmd[1024];
Com_sprintf( cmd, sizeof( cmd ), "%c%s %d %d\n",
( down ) ? '+' : '-', p + 1, key, time );
Cbuf_AddText( cmd );
}
*buttonPtr++ = kb[i];
if ( !kb[i] ) {
else if( down )
{
// normal commands only execute on key press
Cbuf_AddText( p );
Cbuf_AddText( "\n" );
}
if( !end )
break;
}
p = end + 1;
}
}
/*
===================
CL_KeyEvent
CL_KeyDownEvent
Called by the system for both key up and key down events
Called by CL_KeyEvent to handle a keypress
===================
*/
void CL_KeyEvent (int key, qboolean down, unsigned time) {
char *kb;
char cmd[1024];
void CL_KeyDownEvent( int key, unsigned time )
{
keys[key].down = qtrue;
keys[key].repeats++;
if( keys[key].repeats == 1 )
anykeydown++;
// update auto-repeat status and BUTTON_ANY status
keys[key].down = down;
if (down) {
keys[key].repeats++;
if ( keys[key].repeats == 1) {
anykeydown++;
}
} else {
keys[key].repeats = 0;
anykeydown--;
if (anykeydown < 0) {
anykeydown = 0;
}
}
if (key == K_ENTER)
if( keys[K_ALT].down && key == K_ENTER )
{
if (down)
{
if (keys[K_ALT].down)
{
Cvar_SetValue( "r_fullscreen",
!Cvar_VariableIntegerValue( "r_fullscreen" ) );
return;
}
}
Cvar_SetValue( "r_fullscreen",
!Cvar_VariableIntegerValue( "r_fullscreen" ) );
return;
}
// console key is hardcoded, so the user can never unbind it
if (key == K_CONSOLE ||
( key == K_ESCAPE && keys[K_SHIFT].down ) ) {
if (!down) {
return;
}
if( key == K_CONSOLE || ( keys[K_SHIFT].down && key == K_ESCAPE ) )
{
Con_ToggleConsole_f ();
Key_ClearStates ();
return;
@ -1213,7 +1191,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
// keys can still be used for bound actions
if ( down && ( key < 128 || key == K_MOUSE1 ) &&
if ( ( key < 128 || key == K_MOUSE1 ) &&
( clc.demoplaying || cls.state == CA_CINEMATIC ) && Key_GetCatcher( ) == 0 ) {
if (Cvar_VariableValue ("com_cameraMode") == 0) {
@ -1222,9 +1200,8 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
}
}
// escape is always handled special
if ( key == K_ESCAPE && down ) {
if ( key == K_ESCAPE ) {
if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) {
// clear message mode
Message_Key( key );
@ -1250,43 +1227,20 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
return;
}
VM_Call( uivm, UI_KEY_EVENT, key, down );
VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
return;
}
//
// key up events only perform actions if the game key binding is
// a button command (leading + sign). These will be processed even in
// console mode and menu mode, to keep the character from continuing
// an action started before a mode switch.
//
if (!down ) {
if ( cls.state != CA_DISCONNECTED ) {
kb = keys[key].binding;
CL_AddKeyUpCommands( key, kb, time );
}
if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
VM_Call( uivm, UI_KEY_EVENT, key, down );
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) {
VM_Call( cgvm, CG_KEY_EVENT, key, down );
}
return;
}
// distribute the key down event to the apropriate handler
if ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) {
Console_Key( key );
} else if ( Key_GetCatcher( ) & KEYCATCH_UI ) {
if ( uivm ) {
VM_Call( uivm, UI_KEY_EVENT, key, down );
VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
}
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME ) {
if ( cgvm ) {
VM_Call( cgvm, CG_KEY_EVENT, key, down );
VM_Call( cgvm, CG_KEY_EVENT, key, qtrue );
}
} else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) {
Message_Key( key );
@ -1294,47 +1248,60 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
Console_Key( key );
} else {
// send the bound action
kb = keys[key].binding;
if ( !kb ) {
if (key >= 200) {
Com_Printf ("%s is unbound, use controls menu to set.\n"
, Key_KeynumToString( key ) );
}
} else if (kb[0] == '+') {
int i;
char button[1024], *buttonPtr;
buttonPtr = button;
for ( i = 0; ; i++ ) {
if ( kb[i] == ';' || !kb[i] ) {
*buttonPtr = '\0';
if ( button[0] == '+') {
// button commands add keynum and time as parms so that multiple
// sources can be discriminated and subframe corrected
Com_sprintf (cmd, sizeof(cmd), "%s %i %i\n", button, key, time);
Cbuf_AddText (cmd);
} else {
// down-only command
Cbuf_AddText (button);
Cbuf_AddText ("\n");
}
buttonPtr = button;
while ( (kb[i] <= ' ' || kb[i] == ';') && kb[i] != 0 ) {
i++;
}
}
*buttonPtr++ = kb[i];
if ( !kb[i] ) {
break;
}
}
} else {
// down-only command
Cbuf_AddText (kb);
Cbuf_AddText ("\n");
}
CL_ParseBinding( key, qtrue, time );
}
return;
}
/*
===================
CL_KeyUpEvent
Called by CL_KeyEvent to handle a keyrelease
===================
*/
void CL_KeyUpEvent( int key, unsigned time )
{
keys[key].repeats = 0;
keys[key].down = qfalse;
anykeydown--;
if (anykeydown < 0) {
anykeydown = 0;
}
// don't process key-up events for the console key
if ( key == K_CONSOLE || ( key == K_ESCAPE && keys[K_SHIFT].down ) )
return;
//
// key up events only perform actions if the game key binding is
// a button command (leading + sign). These will be processed even in
// console mode and menu mode, to keep the character from continuing
// an action started before a mode switch.
//
if( cls.state != CA_DISCONNECTED )
CL_ParseBinding( key, qfalse, time );
if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
VM_Call( uivm, UI_KEY_EVENT, key, qfalse );
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) {
VM_Call( cgvm, CG_KEY_EVENT, key, qfalse );
}
}
/*
===================
CL_KeyEvent
Called by the system for both key up and key down events
===================
*/
void CL_KeyEvent (int key, qboolean down, unsigned time) {
if( down )
CL_KeyDownEvent( key, time );
else
CL_KeyUpEvent( key, time );
}
/*
===================