Fix gamepad pseudo-mouse input for UIs in multiplayer mode

also, only generate pseudo-mouse-move events for gamecode
(by modifying idUsercmdGenLocal::continuousMouseX/Y) when an
interactive ingame UI is active
This commit is contained in:
Daniel Gibson 2024-01-17 16:47:21 +01:00
parent 03ec74fd6f
commit cf5d10f4e6
6 changed files with 56 additions and 17 deletions

View file

@ -1447,6 +1447,9 @@ void idSessionLocal::UnloadMap() {
}
mapSpawned = false;
// DG: that state needs to be reset now
Sys_SetInteractiveIngameGuiActive( false, NULL );
}
/*

View file

@ -890,12 +890,15 @@ static float joyAxisToMouseDelta(float axis, float deadzone)
return ret;
}
extern bool D3_IN_interactiveIngameGuiActive; // from sys/events.cpp
void idUsercmdGenLocal::JoystickFakeMouse(float axis_x, float axis_y, float deadzone)
{
float x = joyAxisToMouseDelta(axis_x, deadzone);
float y = joyAxisToMouseDelta(axis_y, deadzone);
continuousMouseX += x;
continuousMouseY += y;
if ( D3_IN_interactiveIngameGuiActive ) {
float x = joyAxisToMouseDelta(axis_x, deadzone);
float y = joyAxisToMouseDelta(axis_y, deadzone);
continuousMouseX += x;
continuousMouseY += y;
}
}
/*

View file

@ -96,8 +96,8 @@ public:
signed char rightmove; // left/right movement
signed char upmove; // up/down movement
short angles[3]; // view angles
short mx; // mouse delta x
short my; // mouse delta y
short mx; // mouse delta x - DG: not really delta, but from continuousMouseX which accumulates
short my; // mouse delta y - DG: same but from continuousMouseY
signed char impulse; // impulse command
byte flags; // additional flags
int sequence; // just for debugging

View file

@ -899,7 +899,7 @@ void Sys_GrabMouseCursor(bool grabIt) {
GLimp_GrabInput(flags);
}
static bool interactiveGuiActive = false;
/*
===============
Sys_SetInteractiveIngameGuiActive
@ -910,12 +910,42 @@ left mouse button in that case, so "clicking" with gamepad in the PDA
(and ingame GUIs) works as expected.
Not set for proper menus like main menu etc - the gamepad hacks for that
are in idUserInterfaceLocal::HandleEvent().
Call with ui = NULL to clear the state.
I hope this won't explode in my face :-p
===============
*/
void Sys_SetInteractiveIngameGuiActive(bool active)
*/
bool D3_IN_interactiveIngameGuiActive = false;
void Sys_SetInteractiveIngameGuiActive( bool active, idUserInterface* ui )
{
interactiveGuiActive = active;
static idList<idUserInterface*> lastuis;
if ( ui == NULL ) {
// special case for clearing
D3_IN_interactiveIngameGuiActive = false;
lastuis.Clear();
return;
}
int idx = lastuis.FindIndex( ui );
if ( sessLocal.GetActiveMenu() == NULL && active ) {
// add ui to lastuis, if it has been activated and no proper menu
// (like main menu) is currently open
lastuis.Append( ui );
} else if ( idx != -1 ) {
// if the UI is in lastuis and has been deactivated, or there
// is a proper menu opened, remove it from the list.
// this both handles the regular deactivate case and also works around
// main-menu-in-multiplayer weirdness: that menu calls idUserInterface::Activate()
// with activate = true twice, but on first call sessLocal.GetActiveMenu() is NULL
// so we want to remove it once we realize that it really is a "proper" menu after all.
// And because it's possible that we have an ingame UI focussed while opening
// the multiplayer-main-menu, we keep a list of lastuis, instead of just one,
// so D3_IN_interactiveIngameGuiActive remains true in that case
// (the ingame UI is still in the list)
lastuis.RemoveIndex( idx );
}
D3_IN_interactiveIngameGuiActive = lastuis.Num() != 0;
}
@ -1247,7 +1277,7 @@ sysEvent_t Sys_GetEvent() {
if ( ev.cbutton.button == SDL_CONTROLLER_BUTTON_START ) {
res.evValue = K_ESCAPE;
return res;
} else if( ev.cbutton.button == SDL_CONTROLLER_BUTTON_A && interactiveGuiActive && sessLocal.GetActiveMenu() == NULL ) {
} else if( ev.cbutton.button == SDL_CONTROLLER_BUTTON_A && D3_IN_interactiveIngameGuiActive && sessLocal.GetActiveMenu() == NULL ) {
// ugly hack: currently an interactive ingame GUI (with a cursor) is active/focused
// so pretend that the gamepads A (south) button is the left mouse button
// so it can be used for "clicking"..

View file

@ -251,7 +251,8 @@ void Sys_GrabMouseCursor( bool grabIt );
// DG: added this for an ungodly hack for gamepad support
// active = true means "currently a GUI with a cursor is active/focused"
// active = false means "that GUI is not active anymore"
void Sys_SetInteractiveIngameGuiActive(bool active);
class idUserInterface;
void Sys_SetInteractiveIngameGuiActive( bool active, idUserInterface* ui );
void Sys_ShowWindow( bool show );
bool Sys_IsWindowVisible( void );

View file

@ -118,6 +118,9 @@ void idUserInterfaceManagerLocal::EndLevelLoad() {
}
}
}
// DG: this should probably be reset at this point
Sys_SetInteractiveIngameGuiActive( false, NULL );
}
void idUserInterfaceManagerLocal::Reload( bool all ) {
@ -582,11 +585,10 @@ const char *idUserInterfaceLocal::Activate(bool activate, int _time) {
time = _time;
active = activate;
if ( desktop ) {
// FIXME: this works ok, mostly, except in multiplayer, where this function
// is called twice with activate=true, and the first time GetActiveMenu() returns NULL, the second time not
if(interactive && sessLocal.GetActiveMenu() == NULL) {
Sys_SetInteractiveIngameGuiActive(activate);
}
// DG: added this hack for gamepad input
if ( interactive ) {
Sys_SetInteractiveIngameGuiActive( activate, this );
} // DG end
activateStr = "";
desktop->Activate( activate, activateStr );
return activateStr;