Browse Source

engine: client: touch: generalise touch emulation code

* fix doubleclicks and wheels in VGUI
pull/2/head
Alibek Omarov 2 years ago
parent
commit
2d2523df4a
  1. 98
      engine/client/in_touch.c
  2. 64
      engine/client/input.c
  3. 5
      engine/client/input.h
  4. 1
      engine/client/keys.c
  5. 69
      engine/client/vgui/vgui_draw.c
  6. 2
      engine/client/vgui/vgui_draw.h
  7. 19
      engine/platform/linux/in_evdev.c
  8. 37
      engine/platform/sdl/events.c
  9. 7
      engine/platform/sdl/in_sdl.c

98
engine/client/in_touch.c

@ -151,7 +151,6 @@ convar_t *touch_exp_mult;
convar_t *touch_grid_enable; convar_t *touch_grid_enable;
convar_t *touch_grid_count; convar_t *touch_grid_count;
convar_t *touch_config_file; convar_t *touch_config_file;
convar_t *touch_enable;
convar_t *touch_in_menu; convar_t *touch_in_menu;
convar_t *touch_joy_radius; convar_t *touch_joy_radius;
convar_t *touch_dpad_radius; convar_t *touch_dpad_radius;
@ -162,7 +161,9 @@ convar_t *touch_highlight_b;
convar_t *touch_highlight_a; convar_t *touch_highlight_a;
convar_t *touch_precise_amount; convar_t *touch_precise_amount;
convar_t *touch_joy_texture; convar_t *touch_joy_texture;
convar_t *touch_emulate;
CVAR_DEFINE_AUTO( touch_enable, DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" );
CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" );
// code looks smaller with it // code looks smaller with it
#define B(x) (button->x) #define B(x) (button->x)
@ -1080,8 +1081,8 @@ void Touch_Init( void )
touch_joy_texture = Cvar_Get( "touch_joy_texture", "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator"); touch_joy_texture = Cvar_Get( "touch_joy_texture", "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator");
// input devices cvar // input devices cvar
touch_enable = Cvar_Get( "touch_enable", DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" ); Cvar_RegisterVariable( &touch_enable );
touch_emulate = Cvar_Get( "touch_emulate", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" ); Cvar_RegisterVariable( &touch_emulate );
/// TODO: touch sdl platform /// TODO: touch sdl platform
// SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" ); // SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
@ -1343,7 +1344,7 @@ void Touch_Draw( void )
{ {
touch_button_t *button; touch_button_t *button;
if( !touch.initialized || (!CVAR_TO_BOOL(touch_enable) && !touch.clientonly) ) if( !touch.initialized || ( !touch_enable.value && !touch.clientonly ))
return; return;
Touch_InitConfig(); Touch_InitConfig();
@ -1937,9 +1938,8 @@ static int Touch_ControlsEvent( touchEventType type, int fingerID, float x, floa
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy ) int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy )
{ {
// simulate menu mouse click // simulate menu mouse click
if( cls.key_dest != key_game && !CVAR_TO_BOOL(touch_in_menu) ) if( cls.key_dest != key_game && !CVAR_TO_BOOL( touch_in_menu ))
{ {
touch.move_finger = touch.resize_finger = touch.look_finger = -1; touch.move_finger = touch.resize_finger = touch.look_finger = -1;
// Hack for keyboard, hope it help // Hack for keyboard, hope it help
@ -1982,25 +1982,20 @@ int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx
{ {
VGui_MouseMove( TO_SCRN_X(x), TO_SCRN_Y(y) ); VGui_MouseMove( TO_SCRN_X(x), TO_SCRN_Y(y) );
if( type != event_motion ) switch( type )
VGui_KeyEvent( K_MOUSE1, type == event_down ? 1 : 0 ); {
case event_down:
// allow scoreboard scroll VGui_MouseEvent( K_MOUSE1, 1 );
if( host.mouse_visible && type == event_motion ) break;
return 0; case event_up:
VGui_MouseEvent( K_MOUSE1, 0 );
break;
default: break;
}
} }
if( !touch.initialized || (!CVAR_TO_BOOL(touch_enable) && !touch.clientonly) ) if( !touch.initialized || ( !touch_enable.value && !touch.clientonly ))
{
#if 0
if( type == event_down )
Key_Event( K_MOUSE1, true );
if( type == event_up )
Key_Event( K_MOUSE1, false );
Android_AddMove( dx * (float)refState.width, dy * (float)refState.height );
#endif
return 0; return 0;
}
if( clgame.dllFuncs.pfnTouchEvent && clgame.dllFuncs.pfnTouchEvent( type, fingerID, x, y, dx, dy ) ) if( clgame.dllFuncs.pfnTouchEvent && clgame.dllFuncs.pfnTouchEvent( type, fingerID, x, y, dx, dy ) )
return true; return true;
@ -2019,35 +2014,60 @@ void Touch_GetMove( float *forward, float *side, float *yaw, float *pitch )
void Touch_KeyEvent( int key, int down ) void Touch_KeyEvent( int key, int down )
{ {
int xi, yi;
float x, y;
static float lx, ly; static float lx, ly;
static int kidNamedFinger = -1;
touchEventType event;
float x, y;
int finger, xi, yi;
if( !CVAR_TO_BOOL(touch_emulate) ) if( !touch_emulate.value )
{ {
if( CVAR_TO_BOOL(touch_enable) ) if( touch_enable.value )
return; return;
if( !touch.clientonly ) if( !touch.clientonly )
return; return;
} }
Platform_GetMousePos( &xi, &yi ); if( !key )
{
x = xi/SCR_W; if( kidNamedFinger < 0 )
y = yi/SCR_H; return;
if( cls.key_dest == key_menu && down < 2 && key == K_MOUSE1 ) finger = kidNamedFinger;
event = event_motion;
}
else
{
finger = key == K_MOUSE1 ? 0 : 1;
if( down )
{ {
UI_MouseMove( xi, yi ); event = event_down;
UI_KeyEvent( key, down ); kidNamedFinger = finger;
} }
if( down == 1 )
Touch_ControlsEvent( event_down, key == K_MOUSE1?0:1, x, y, 0, 0 );
else else
Touch_ControlsEvent( down? event_motion: event_up, key == K_MOUSE1?0:1, x, y, x-lx, y-ly ); {
lx = x, ly = y; event = event_up;
kidNamedFinger = -1;
}
}
// don't deactivate mouse in game
// checking a case when mouse and touchscreen
// can be used simultaneously
Platform_SetCursorType( dc_arrow );
Platform_GetMousePos( &xi, &yi );
x = xi / SCR_W;
y = yi / SCR_H;
Con_DPrintf( "event %d %.2f %.2f %.2f %.2f\n",
event, x, y, x - lx, y - ly );
IN_TouchEvent( event, finger, x, y, x - lx, y - ly );
lx = x;
ly = y;
} }
void Touch_Shutdown( void ) void Touch_Shutdown( void )

64
engine/client/input.c

@ -63,7 +63,7 @@ uint IN_CollectInputDevices( void )
if( !m_ignore->value ) // no way to check is mouse connected, so use cvar only if( !m_ignore->value ) // no way to check is mouse connected, so use cvar only
ret |= INPUT_DEVICE_MOUSE; ret |= INPUT_DEVICE_MOUSE;
if( CVAR_TO_BOOL(touch_enable) ) if( touch_enable.value )
ret |= INPUT_DEVICE_TOUCH; ret |= INPUT_DEVICE_TOUCH;
if( Joy_IsActive() ) // connected or enabled if( Joy_IsActive() ) // connected or enabled
@ -94,13 +94,13 @@ void IN_LockInputDevices( qboolean lock )
{ {
SetBits( m_ignore->flags, FCVAR_READ_ONLY ); SetBits( m_ignore->flags, FCVAR_READ_ONLY );
SetBits( joy_enable->flags, FCVAR_READ_ONLY ); SetBits( joy_enable->flags, FCVAR_READ_ONLY );
SetBits( touch_enable->flags, FCVAR_READ_ONLY ); SetBits( touch_enable.flags, FCVAR_READ_ONLY );
} }
else else
{ {
ClearBits( m_ignore->flags, FCVAR_READ_ONLY ); ClearBits( m_ignore->flags, FCVAR_READ_ONLY );
ClearBits( joy_enable->flags, FCVAR_READ_ONLY ); ClearBits( joy_enable->flags, FCVAR_READ_ONLY );
ClearBits( touch_enable->flags, FCVAR_READ_ONLY ); ClearBits( touch_enable.flags, FCVAR_READ_ONLY );
} }
} }
@ -308,25 +308,39 @@ IN_MouseMove
*/ */
void IN_MouseMove( void ) void IN_MouseMove( void )
{ {
POINT current_pos; int x, y;
if( !in_mouseinitialized ) if( !in_mouseinitialized )
return; return;
if( FBitSet( touch_emulate.flags, FCVAR_CHANGED ))
{
// FIXME: do not hide cursor if it was requested by GUI
if( !touch_emulate.value )
Platform_SetCursorType( dc_none );
ClearBits( touch_emulate.flags, FCVAR_CHANGED );
}
if( touch_emulate.value )
{
// touch emulation overrides all input
Touch_KeyEvent( 0, 0 );
return;
}
// find mouse movement // find mouse movement
Platform_GetMousePos( &current_pos.x, &current_pos.y ); Platform_GetMousePos( &x, &y );
VGui_MouseMove( current_pos.x, current_pos.y ); VGui_MouseMove( x, y );
// HACKHACK: show cursor in UI, as mainui doesn't call // HACKHACK: show cursor in UI, as mainui doesn't call
// platform-dependent SetCursor anymore // platform-dependent SetCursor anymore
#if XASH_SDL if( UI_IsVisible( ))
if( UI_IsVisible() ) Platform_SetCursorType( dc_arrow );
SDL_ShowCursor( SDL_TRUE );
#endif
// if the menu is visible, move the menu cursor // if the menu is visible, move the menu cursor
UI_MouseMove( current_pos.x, current_pos.y ); UI_MouseMove( x, y );
} }
/* /*
@ -336,8 +350,6 @@ IN_MouseEvent
*/ */
void IN_MouseEvent( int key, int down ) void IN_MouseEvent( int key, int down )
{ {
int i;
if( !in_mouseinitialized ) if( !in_mouseinitialized )
return; return;
@ -345,10 +357,15 @@ void IN_MouseEvent( int key, int down )
SetBits( in_mstate, BIT( key )); SetBits( in_mstate, BIT( key ));
else ClearBits( in_mstate, BIT( key )); else ClearBits( in_mstate, BIT( key ));
if( cls.key_dest == key_game ) // touch emulation overrides all input
if( touch_emulate.value )
{
Touch_KeyEvent( K_MOUSE1 + key, down );
}
else if( cls.key_dest == key_game )
{ {
// perform button actions // perform button actions
VGui_KeyEvent( K_MOUSE1 + key, down ); VGui_MouseEvent( K_MOUSE1 + key, down );
// don't do Key_Event here // don't do Key_Event here
// client may override IN_MouseEvent // client may override IN_MouseEvent
@ -363,6 +380,23 @@ void IN_MouseEvent( int key, int down )
} }
} }
/*
==============
IN_MWheelEvent
direction is negative for wheel down, otherwise wheel up
==============
*/
void IN_MWheelEvent( int y )
{
int b = y > 0 ? K_MWHEELUP : K_MWHEELDOWN;
VGui_MWheelEvent( y );
Key_Event( b, true );
Key_Event( b, false );
}
/* /*
=========== ===========
IN_Shutdown IN_Shutdown

5
engine/client/input.h

@ -34,6 +34,7 @@ void IN_Init( void );
void Host_InputFrame( void ); void Host_InputFrame( void );
void IN_Shutdown( void ); void IN_Shutdown( void );
void IN_MouseEvent( int key, int down ); void IN_MouseEvent( int key, int down );
void IN_MWheelEvent( int direction );
void IN_ActivateMouse( void ); void IN_ActivateMouse( void );
void IN_DeactivateMouse( void ); void IN_DeactivateMouse( void );
void IN_MouseSavePos( void ); void IN_MouseSavePos( void );
@ -57,8 +58,8 @@ typedef enum
event_motion event_motion
} touchEventType; } touchEventType;
extern convar_t *touch_enable; extern convar_t touch_enable;
extern convar_t *touch_emulate; extern convar_t touch_emulate;
void Touch_Draw( void ); void Touch_Draw( void );
void Touch_SetClientOnly( byte state ); void Touch_SetClientOnly( byte state );

1
engine/client/keys.c

@ -712,7 +712,6 @@ void GAME_EXPORT Key_Event( int key, int down )
} }
VGui_KeyEvent( key, down ); VGui_KeyEvent( key, down );
Touch_KeyEvent( key, down );
// console key is hardcoded, so the user can never unbind it // console key is hardcoded, so the user can never unbind it
if( key == '`' || key == '~' ) if( key == '`' || key == '~' )

69
engine/client/vgui/vgui_draw.c

@ -402,9 +402,8 @@ enum VGUI_KeyCode VGUI_MapKey( int keyCode )
{ {
VGUI_InitKeyTranslationTable(); VGUI_InitKeyTranslationTable();
if( keyCode < 0 || keyCode >= (int)sizeof( s_pVirtualKeyTrans ) / (int)sizeof( s_pVirtualKeyTrans[0] )) if( keyCode < 0 || keyCode >= ARRAYSIZE( s_pVirtualKeyTrans ))
{ {
//Assert( false );
return (enum VGUI_KeyCode)-1; return (enum VGUI_KeyCode)-1;
} }
else else
@ -413,48 +412,66 @@ enum VGUI_KeyCode VGUI_MapKey( int keyCode )
} }
} }
void VGui_KeyEvent( int key, int down ) void VGui_MouseEvent( int key, int clicks )
{ {
enum VGUI_MouseAction mact;
enum VGUI_MouseCode code;
if( !vgui.initialized ) if( !vgui.initialized )
return; return;
switch( key ) switch( key )
{ {
case K_MOUSE1: case K_MOUSE1: code = MOUSE_LEFT; break;
if( down && host.mouse_visible ) { case K_MOUSE2: code = MOUSE_RIGHT; break;
Key_EnableTextInput(true, false); case K_MOUSE3: code = MOUSE_MIDDLE; break;
default: return;
} }
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_LEFT );
return; if( clicks >= 2 )
case K_MOUSE2: mact = MA_DOUBLE;
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_RIGHT ); else if( clicks == 1 )
return; mact = MA_PRESSED;
case K_MOUSE3: else
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_MIDDLE ); mact = MA_RELEASED;
vgui.Mouse( mact, code );
}
void VGui_MWheelEvent( int y )
{
if( !vgui.initialized )
return; return;
case K_MWHEELDOWN:
vgui.Mouse( MA_WHEEL, 1 ); vgui.Mouse( MA_WHEEL, y );
}
void VGui_KeyEvent( int key, int down )
{
enum VGUI_KeyCode code;
if( !vgui.initialized )
return; return;
case K_MWHEELUP:
vgui.Mouse( MA_WHEEL, -1 ); if(( code = VGUI_MapKey( key )) < 0 )
return; return;
default:
break;
}
if( down == 2 ) if( down )
vgui.Key( KA_TYPED, VGUI_MapKey( key ) ); {
else vgui.Key( KA_PRESSED, code );
vgui.Key( down?KA_PRESSED:KA_RELEASED, VGUI_MapKey( key ) ); vgui.Key( KA_TYPED, code );
//Msg("VGui_KeyEvent %d %d %d\n", key, VGUI_MapKey( key ), down ); }
else vgui.Key( KA_RELEASED, code );
} }
void VGui_MouseMove( int x, int y ) void VGui_MouseMove( int x, int y )
{ {
if( vgui.initialized )
{
float xscale = (float)refState.width / (float)clgame.scrInfo.iWidth; float xscale = (float)refState.width / (float)clgame.scrInfo.iWidth;
float yscale = (float)refState.height / (float)clgame.scrInfo.iHeight; float yscale = (float)refState.height / (float)clgame.scrInfo.iHeight;
if( vgui.initialized )
vgui.MouseMove( x / xscale, y / yscale ); vgui.MouseMove( x / xscale, y / yscale );
}
} }
void VGui_Paint( void ) void VGui_Paint( void )

2
engine/client/vgui/vgui_draw.h

@ -29,6 +29,8 @@ void VGui_Startup( const char *clientlib, int width, int height );
void VGui_Shutdown( void ); void VGui_Shutdown( void );
void VGui_Paint( void ); void VGui_Paint( void );
void VGui_RunFrame( void ); void VGui_RunFrame( void );
void VGui_MouseEvent( int key, int clicks );
void VGui_MWheelEvent( int y );
void VGui_KeyEvent( int key, int down ); void VGui_KeyEvent( int key, int down );
void VGui_MouseMove( int x, int y ); void VGui_MouseMove( int x, int y );
qboolean VGui_IsActive( void ); qboolean VGui_IsActive( void );

19
engine/platform/linux/in_evdev.c

@ -343,23 +343,16 @@ void IN_EvdevFrame ( void )
{ {
switch ( ev.code ) switch ( ev.code )
{ {
case REL_X: dx += ev.value; case REL_X:
dx += ev.value;
break; break;
case REL_Y: dy += ev.value; case REL_Y:
dy += ev.value;
break; break;
case REL_WHEEL: case REL_WHEEL:
if( ev.value > 0) IN_MWheelEvent( ev.value );
{
Key_Event( K_MWHEELDOWN, 1 );
Key_Event( K_MWHEELDOWN, 0 );
}
else
{
Key_Event( K_MWHEELUP, 1 );
Key_Event( K_MWHEELUP, 0 );
}
break; break;
} }
} }
@ -367,7 +360,7 @@ void IN_EvdevFrame ( void )
{ {
int key = KeycodeFromEvdev( ev.code, ev.value ); int key = KeycodeFromEvdev( ev.code, ev.value );
if( CVAR_TO_BOOL(evdev_keydebug) ) if( CVAR_TO_BOOL( evdev_keydebug ))
Con_Printf( "key %d %d %d\n", ev.code, key, ev.value ); Con_Printf( "key %d %d %d\n", ev.code, key, ev.value );
Key_Event( key , ev.value ); Key_Event( key , ev.value );

37
engine/platform/sdl/events.c

@ -250,18 +250,6 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
Key_Event( keynum, down ); Key_Event( keynum, down );
} }
static void SDLash_MouseKey( int key, int down, int istouch )
{
if( CVAR_TO_BOOL( touch_emulate ) )
{
Touch_KeyEvent( key, down );
}
else if( in_mouseinitialized && !m_ignore->value && !istouch )
{
Key_Event( key, down );
}
}
/* /*
============= =============
SDLash_MouseEvent SDLash_MouseEvent
@ -270,14 +258,20 @@ SDLash_MouseEvent
*/ */
static void SDLash_MouseEvent( SDL_MouseButtonEvent button ) static void SDLash_MouseEvent( SDL_MouseButtonEvent button )
{ {
int down = button.state != SDL_RELEASED; int down;
uint mstate = 0;
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) #if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( button.which == SDL_TOUCH_MOUSEID ) if( button.which == SDL_TOUCH_MOUSEID )
return; return;
#endif #endif
if( button.state == SDL_RELEASED )
down = 0;
else if( button.clicks >= 2 )
down = 2; // special state for double-click in UI
else
down = 1;
switch( button.button ) switch( button.button )
{ {
case SDL_BUTTON_LEFT: case SDL_BUTTON_LEFT:
@ -297,10 +291,10 @@ static void SDLash_MouseEvent( SDL_MouseButtonEvent button )
break; break;
#if ! SDL_VERSION_ATLEAST( 2, 0, 0 ) #if ! SDL_VERSION_ATLEAST( 2, 0, 0 )
case SDL_BUTTON_WHEELUP: case SDL_BUTTON_WHEELUP:
Key_Event( K_MWHEELUP, down ); IN_MWheelEvent( -1 );
break; break;
case SDL_BUTTON_WHEELDOWN: case SDL_BUTTON_WHEELDOWN:
Key_Event( K_MWHEELDOWN, down ); IN_MWheelEvent( 1 );
break; break;
#endif // ! SDL_VERSION_ATLEAST( 2, 0, 0 ) #endif // ! SDL_VERSION_ATLEAST( 2, 0, 0 )
default: default:
@ -435,9 +429,7 @@ static void SDLash_EventFilter( SDL_Event *event )
/* Mouse events */ /* Mouse events */
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
if( host.mouse_visible ) if( host.mouse_visible )
{
SDL_GetRelativeMouseState( NULL, NULL ); SDL_GetRelativeMouseState( NULL, NULL );
}
break; break;
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
@ -478,12 +470,8 @@ static void SDLash_EventFilter( SDL_Event *event )
break; break;
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) #if SDL_VERSION_ATLEAST( 2, 0, 0 )
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
{ IN_MWheelEvent( event->wheel.y );
int wheelbutton = event->wheel.y < 0 ? K_MWHEELDOWN : K_MWHEELUP;
Key_Event( wheelbutton, true );
Key_Event( wheelbutton, false );
break; break;
}
/* Touch events */ /* Touch events */
case SDL_FINGERDOWN: case SDL_FINGERDOWN:
@ -556,7 +544,8 @@ static void SDLash_EventFilter( SDL_Event *event )
{ {
// Swap axis to follow default axis binding: // Swap axis to follow default axis binding:
// LeftX, LeftY, RightX, RightY, TriggerRight, TriggerLeft // LeftX, LeftY, RightX, RightY, TriggerRight, TriggerLeft
static int sdlControllerAxisToEngine[] = { static int sdlControllerAxisToEngine[] =
{
JOY_AXIS_SIDE, // SDL_CONTROLLER_AXIS_LEFTX, JOY_AXIS_SIDE, // SDL_CONTROLLER_AXIS_LEFTX,
JOY_AXIS_FWD, // SDL_CONTROLLER_AXIS_LEFTY, JOY_AXIS_FWD, // SDL_CONTROLLER_AXIS_LEFTY,
JOY_AXIS_PITCH, // SDL_CONTROLLER_AXIS_RIGHTX, JOY_AXIS_PITCH, // SDL_CONTROLLER_AXIS_RIGHTX,

7
engine/platform/sdl/in_sdl.c

@ -333,11 +333,12 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
break; break;
} }
host.mouse_visible = visible; // never disable cursor in touch emulation mode
if( !visible && touch_emulate.value )
if( CVAR_TO_BOOL( touch_emulate ))
return; return;
host.mouse_visible = visible;
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) #if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( host.mouse_visible ) if( host.mouse_visible )
{ {

Loading…
Cancel
Save