Integrate joystick with game controls and menus/editor UI

This commit is contained in:
Robert Müller 2022-06-06 22:03:24 +02:00
parent 8757b1f41e
commit 55d48db711
17 changed files with 84 additions and 43 deletions

View file

@ -255,8 +255,6 @@ bool CInput::MouseRelative(float *pX, float *pY)
return false;
int nx = 0, ny = 0;
float Sens = g_Config.m_InpMousesens / 100.0f;
#if defined(CONF_PLATFORM_ANDROID) // No relative mouse on Android
static int s_LastX = 0;
static int s_LastY = 0;
@ -267,13 +265,12 @@ bool CInput::MouseRelative(float *pX, float *pY)
s_LastY = ny;
nx = XTmp;
ny = YTmp;
Sens = 1;
#else
SDL_GetRelativeMouseState(&nx, &ny);
#endif
*pX = nx * Sens;
*pY = ny * Sens;
*pX = nx;
*pY = ny;
return *pX != 0.0f || *pY != 0.0f;
}

View file

@ -199,8 +199,9 @@ public:
*
* @param x The amount of change in the x coordinate since the last call.
* @param y The amount of change in the y coordinate since the last call.
* @param CursorType The type of cursor that caused the movement.
*/
virtual bool OnMouseMove(float x, float y) { return false; }
virtual bool OnCursorMove(float x, float y, IInput::ECursorType CursorType) { return false; }
/**
* Called on a input event.
* @param e The input event.

View file

@ -365,26 +365,46 @@ void CControls::OnRender()
m_TargetPos[g_Config.m_ClDummy] = m_MousePos[g_Config.m_ClDummy];
}
bool CControls::OnMouseMove(float x, float y)
bool CControls::OnCursorMove(float x, float y, IInput::ECursorType CursorType)
{
if((m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags & GAMESTATEFLAG_PAUSED))
if(m_pClient->m_Snap.m_pGameInfoObj && (m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags & GAMESTATEFLAG_PAUSED))
return false;
if(CursorType == IInput::CURSOR_JOYSTICK && g_Config.m_InpJoystickAbsolute && m_pClient->m_Snap.m_pGameInfoObj && !m_pClient->m_Snap.m_SpecInfo.m_Active)
{
float AbsX = 0.0f, AbsY = 0.0f;
if(Input()->GetActiveJoystick()->Absolute(&AbsX, &AbsY))
m_MousePos[g_Config.m_ClDummy] = vec2(AbsX, AbsY) * GetMaxMouseDistance();
return true;
}
float Factor = 1.0f;
if(g_Config.m_ClDyncam && g_Config.m_ClDyncamMousesens)
{
x = x * g_Config.m_ClDyncamMousesens / g_Config.m_InpMousesens;
y = y * g_Config.m_ClDyncamMousesens / g_Config.m_InpMousesens;
Factor = g_Config.m_ClDyncamMousesens / 100.0f;
}
else
{
switch(CursorType)
{
case IInput::CURSOR_MOUSE:
Factor = g_Config.m_InpMousesens / 100.0f;
break;
case IInput::CURSOR_JOYSTICK:
Factor = g_Config.m_InpJoystickSens / 100.0f;
break;
default:
dbg_msg("assert", "CControls::OnCursorMove CursorType %d", (int)CursorType);
dbg_break();
break;
}
}
if(m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID < 0)
{
x = x * m_pClient->m_Camera.m_Zoom;
y = y * m_pClient->m_Camera.m_Zoom;
}
Factor *= m_pClient->m_Camera.m_Zoom;
m_MousePos[g_Config.m_ClDummy] += vec2(x, y); // TODO: ugly
m_MousePos[g_Config.m_ClDummy] += vec2(x, y) * Factor;
ClampMousePos();
return true;
}
@ -397,11 +417,7 @@ void CControls::ClampMousePos()
}
else
{
float CameraMaxDistance = 200.0f;
float FollowFactor = (g_Config.m_ClDyncam ? g_Config.m_ClDyncamFollowFactor : g_Config.m_ClMouseFollowfactor) / 100.0f;
float DeadZone = g_Config.m_ClDyncam ? g_Config.m_ClDyncamDeadzone : g_Config.m_ClMouseDeadzone;
float MaxDistance = g_Config.m_ClDyncam ? g_Config.m_ClDyncamMaxDistance : g_Config.m_ClMouseMaxDistance;
float MouseMax = minimum((FollowFactor != 0 ? CameraMaxDistance / FollowFactor + DeadZone : MaxDistance), MaxDistance);
float MouseMax = GetMaxMouseDistance();
float MinDistance = g_Config.m_ClDyncam ? g_Config.m_ClDyncamMinDistance : g_Config.m_ClMouseMinDistance;
float MouseMin = MinDistance;
@ -419,3 +435,12 @@ void CControls::ClampMousePos()
m_MousePos[g_Config.m_ClDummy] = normalize_pre_length(m_MousePos[g_Config.m_ClDummy], MDistance) * MouseMax;
}
}
float CControls::GetMaxMouseDistance() const
{
float CameraMaxDistance = 200.0f;
float FollowFactor = (g_Config.m_ClDyncam ? g_Config.m_ClDyncamFollowFactor : g_Config.m_ClMouseFollowfactor) / 100.0f;
float DeadZone = g_Config.m_ClDyncam ? g_Config.m_ClDyncamDeadzone : g_Config.m_ClMouseDeadzone;
float MaxDistance = g_Config.m_ClDyncam ? g_Config.m_ClDyncamMaxDistance : g_Config.m_ClMouseMaxDistance;
return minimum((FollowFactor != 0 ? CameraMaxDistance / FollowFactor + DeadZone : MaxDistance), MaxDistance);
}

View file

@ -12,6 +12,8 @@
class CControls : public CComponent
{
float GetMaxMouseDistance() const;
public:
vec2 m_MousePos[NUM_DUMMIES];
vec2 m_TargetPos[NUM_DUMMIES];
@ -35,7 +37,7 @@ public:
virtual void OnRelease() override;
virtual void OnRender() override;
virtual void OnMessage(int MsgType, void *pRawMsg) override;
virtual bool OnMouseMove(float x, float y) override;
virtual bool OnCursorMove(float x, float y, IInput::ECursorType CursorType) override;
virtual void OnConsoleInit() override;
virtual void OnPlayerDeath();

View file

@ -48,12 +48,12 @@ void CEmoticon::OnRelease()
m_Active = false;
}
bool CEmoticon::OnMouseMove(float x, float y)
bool CEmoticon::OnCursorMove(float x, float y, IInput::ECursorType CursorType)
{
if(!m_Active)
return false;
UI()->ConvertMouseMove(&x, &y);
UI()->ConvertMouseMove(&x, &y, CursorType);
m_SelectorMouse += vec2(x, y);
return true;
}

View file

@ -27,7 +27,7 @@ public:
virtual void OnConsoleInit() override;
virtual void OnRender() override;
virtual void OnRelease() override;
virtual bool OnMouseMove(float x, float y) override;
virtual bool OnCursorMove(float x, float y, IInput::ECursorType CursorType) override;
void Emote(int Emoticon);
void EyeEmote(int EyeEmote);

View file

@ -2417,12 +2417,12 @@ void CMenus::OnShutdown()
KillServer();
}
bool CMenus::OnMouseMove(float x, float y)
bool CMenus::OnCursorMove(float x, float y, IInput::ECursorType CursorType)
{
if(!m_MenuActive)
return false;
UIEx()->ConvertMouseMove(&x, &y);
UIEx()->ConvertMouseMove(&x, &y, CursorType);
m_MousePos.x = clamp(m_MousePos.x + x, 0.f, (float)Graphics()->WindowWidth());
m_MousePos.y = clamp(m_MousePos.y + y, 0.f, (float)Graphics()->WindowHeight());

View file

@ -558,7 +558,7 @@ public:
virtual void OnReset() override;
virtual void OnRender() override;
virtual bool OnInput(IInput::CEvent Event) override;
virtual bool OnMouseMove(float x, float y) override;
virtual bool OnCursorMove(float x, float y, IInput::ECursorType CursorType) override;
virtual void OnShutdown() override;
enum

View file

@ -164,12 +164,12 @@ void CSpectator::OnConsoleInit()
Console()->Register("spectate_closest", "", CFGFLAG_CLIENT, ConSpectateClosest, this, "Spectate the closest player");
}
bool CSpectator::OnMouseMove(float x, float y)
bool CSpectator::OnCursorMove(float x, float y, IInput::ECursorType CursorType)
{
if(!m_Active)
return false;
UI()->ConvertMouseMove(&x, &y);
UI()->ConvertMouseMove(&x, &y, CursorType);
m_SelectorMouse += vec2(x, y);
return true;
}

View file

@ -36,7 +36,7 @@ public:
virtual int Sizeof() const override { return sizeof(*this); }
virtual void OnConsoleInit() override;
virtual bool OnMouseMove(float x, float y) override;
virtual bool OnCursorMove(float x, float y, IInput::ECursorType CursorType) override;
virtual void OnRender() override;
virtual void OnRelease() override;
virtual void OnReset() override;

View file

@ -352,11 +352,12 @@ void CGameClient::OnUpdate()
{
// handle mouse movement
float x = 0.0f, y = 0.0f;
if(Input()->MouseRelative(&x, &y))
IInput::ECursorType CursorType = Input()->CursorRelative(&x, &y);
if(CursorType != IInput::CURSOR_NONE)
{
for(auto &pComponent : m_vpInput)
{
if(pComponent->OnMouseMove(x, y))
if(pComponent->OnCursorMove(x, y, CursorType))
break;
}
}

View file

@ -164,11 +164,24 @@ bool CUI::MouseInside(const CUIRect *pRect) const
return pRect->Inside(m_MouseX, m_MouseY);
}
void CUI::ConvertMouseMove(float *x, float *y) const
void CUI::ConvertMouseMove(float *pX, float *pY, IInput::ECursorType CursorType) const
{
float Fac = (float)(g_Config.m_UiMousesens) / g_Config.m_InpMousesens;
*x = *x * Fac;
*y = *y * Fac;
float Factor = 1.0f;
switch(CursorType)
{
case IInput::CURSOR_MOUSE:
Factor = g_Config.m_UiMousesens / 100.0f;
break;
case IInput::CURSOR_JOYSTICK:
Factor = g_Config.m_UiJoystickSens / 100.0f;
break;
default:
dbg_msg("assert", "CUI::ConvertMouseMove CursorType %d", (int)CursorType);
dbg_break();
break;
}
*pX *= Factor;
*pY *= Factor;
}
float CUI::ButtonColorMul(const void *pID)

View file

@ -3,6 +3,7 @@
#ifndef GAME_CLIENT_UI_H
#define GAME_CLIENT_UI_H
#include <engine/input.h>
#include <engine/textrender.h>
#include <chrono>
@ -304,7 +305,7 @@ public:
bool MouseInside(const CUIRect *pRect) const;
bool MouseInsideClip() const { return !IsClipped() || MouseInside(ClipArea()); }
bool MouseHovered(const CUIRect *pRect) const { return MouseInside(pRect) && MouseInsideClip(); }
void ConvertMouseMove(float *x, float *y) const;
void ConvertMouseMove(float *pX, float *pY, IInput::ECursorType CursorType) const;
float ButtonColorMulActive() { return 0.5f; }
float ButtonColorMulHot() { return 1.5f; }

View file

@ -30,9 +30,9 @@ void CUIEx::Init(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools, IInput:
m_pTextRender = Kernel()->RequestInterface<ITextRender>();
}
void CUIEx::ConvertMouseMove(float *pX, float *pY) const
void CUIEx::ConvertMouseMove(float *pX, float *pY, IInput::ECursorType CursorType) const
{
UI()->ConvertMouseMove(pX, pY);
UI()->ConvertMouseMove(pX, pY, CursorType);
if(m_MouseSlow)
{

View file

@ -57,7 +57,7 @@ public:
void Init(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools, IInput::CEvent *pInputEventsArray, int *pInputEventCount);
void ConvertMouseMove(float *pX, float *pY) const;
void ConvertMouseMove(float *pX, float *pY, IInput::ECursorType CursorType) const;
void ResetMouseSlow() { m_MouseSlow = false; }
float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current);

View file

@ -6409,8 +6409,8 @@ void CEditor::UpdateAndRender()
float mx, my, Mwx, Mwy;
float rx = 0, ry = 0;
{
Input()->MouseRelative(&rx, &ry);
UIEx()->ConvertMouseMove(&rx, &ry);
IInput::ECursorType CursorType = Input()->CursorRelative(&rx, &ry);
UIEx()->ConvertMouseMove(&rx, &ry, CursorType);
UIEx()->ResetMouseSlow();
m_MouseDeltaX = rx;

View file

@ -119,6 +119,7 @@ MACRO_CONFIG_INT(UiSettingsPage, ui_settings_page, 0, 0, 9, CFGFLAG_CLIENT | CFG
MACRO_CONFIG_INT(UiToolboxPage, ui_toolbox_page, 0, 0, 2, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Toolbox page")
MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 64, "localhost:8303", CFGFLAG_CLIENT | CFGFLAG_SAVE | CFGFLAG_INSENSITIVE, "Interface server address")
MACRO_CONFIG_INT(UiMousesens, ui_mousesens, 200, 1, 100000, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Mouse sensitivity for menus/editor")
MACRO_CONFIG_INT(UiJoystickSens, ui_joystick_sens, 100, 1, 100000, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Joystick sensitivity for menus/editor")
MACRO_CONFIG_COL(UiColor, ui_color, 0xE4A046AF, CFGFLAG_CLIENT | CFGFLAG_SAVE | CFGFLAG_COLALPHA, "Interface color") // 160 70 175 228 hasalpha