2010-11-20 10:37:14 +00:00
|
|
|
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
2022-06-06 19:19:08 +00:00
|
|
|
#include <SDL.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
#include <base/system.h>
|
2022-06-06 19:19:08 +00:00
|
|
|
#include <engine/console.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/graphics.h>
|
|
|
|
#include <engine/input.h>
|
|
|
|
#include <engine/keys.h>
|
2020-09-22 16:02:03 +00:00
|
|
|
#include <engine/shared/config.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
#include "input.h"
|
|
|
|
|
|
|
|
//print >>f, "int inp_key_code(const char *key_name) { int i; if (!strcmp(key_name, \"-?-\")) return -1; else for (i = 0; i < 512; i++) if (!strcmp(key_strings[i], key_name)) return i; return -1; }"
|
|
|
|
|
|
|
|
// this header is protected so you don't include it from anywere
|
|
|
|
#define KEYS_INCLUDE
|
|
|
|
#include "keynames.h"
|
|
|
|
#undef KEYS_INCLUDE
|
|
|
|
|
2022-06-06 19:19:08 +00:00
|
|
|
// support older SDL version (pre 2.0.6)
|
|
|
|
#ifndef SDL_JOYSTICK_AXIS_MIN
|
|
|
|
#define SDL_JOYSTICK_AXIS_MIN -32768
|
|
|
|
#endif
|
|
|
|
#ifndef SDL_JOYSTICK_AXIS_MAX
|
|
|
|
#define SDL_JOYSTICK_AXIS_MAX 32767
|
|
|
|
#endif
|
|
|
|
|
2016-04-30 02:02:32 +00:00
|
|
|
void CInput::AddEvent(char *pText, int Key, int Flags)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
|
|
|
if(m_NumEvents != INPUT_BUFFER_SIZE)
|
|
|
|
{
|
|
|
|
m_aInputEvents[m_NumEvents].m_Key = Key;
|
|
|
|
m_aInputEvents[m_NumEvents].m_Flags = Flags;
|
2016-04-30 02:02:32 +00:00
|
|
|
if(!pText)
|
|
|
|
m_aInputEvents[m_NumEvents].m_aText[0] = 0;
|
|
|
|
else
|
2021-12-20 01:34:02 +00:00
|
|
|
str_copy(m_aInputEvents[m_NumEvents].m_aText, pText, sizeof(m_aInputEvents[m_NumEvents].m_aText));
|
2016-04-30 18:11:26 +00:00
|
|
|
m_aInputEvents[m_NumEvents].m_InputCount = m_InputCounter;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_NumEvents++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CInput::CInput()
|
|
|
|
{
|
|
|
|
mem_zero(m_aInputCount, sizeof(m_aInputCount));
|
|
|
|
mem_zero(m_aInputState, sizeof(m_aInputState));
|
|
|
|
|
2016-04-30 18:11:26 +00:00
|
|
|
m_InputCounter = 1;
|
2021-10-23 11:48:21 +00:00
|
|
|
m_InputGrabbed = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2019-01-06 09:23:25 +00:00
|
|
|
m_MouseDoubleClick = false;
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
m_NumEvents = 0;
|
2016-05-01 12:00:53 +00:00
|
|
|
m_MouseFocus = true;
|
2014-06-16 11:29:18 +00:00
|
|
|
|
|
|
|
m_VideoRestartNeeded = 0;
|
2015-08-26 14:35:32 +00:00
|
|
|
m_pClipboardText = NULL;
|
2016-08-15 04:01:31 +00:00
|
|
|
|
2020-10-25 15:48:12 +00:00
|
|
|
m_NumTextInputInstances = 0;
|
2020-09-22 16:01:13 +00:00
|
|
|
m_EditingTextLen = -1;
|
|
|
|
m_aEditingText[0] = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CInput::Init()
|
|
|
|
{
|
|
|
|
m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
|
2022-06-06 19:19:08 +00:00
|
|
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
2015-08-24 20:46:28 +00:00
|
|
|
|
2020-09-22 16:01:13 +00:00
|
|
|
// increase ime instance counter for menu
|
|
|
|
SetIMEState(true);
|
2015-08-24 23:48:08 +00:00
|
|
|
MouseModeRelative();
|
2022-06-06 19:19:08 +00:00
|
|
|
|
|
|
|
InitJoysticks();
|
|
|
|
}
|
|
|
|
|
2022-06-18 09:57:57 +00:00
|
|
|
void CInput::Shutdown()
|
|
|
|
{
|
|
|
|
SDL_free(m_pClipboardText);
|
|
|
|
CloseJoysticks();
|
|
|
|
}
|
|
|
|
|
2022-06-06 19:19:08 +00:00
|
|
|
void CInput::InitJoysticks()
|
|
|
|
{
|
|
|
|
if(!SDL_WasInit(SDL_INIT_JOYSTICK))
|
|
|
|
{
|
|
|
|
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
|
|
|
|
{
|
|
|
|
dbg_msg("joystick", "Unable to init SDL joystick system: %s", SDL_GetError());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int NumJoysticks = SDL_NumJoysticks();
|
|
|
|
if(NumJoysticks > 0)
|
|
|
|
{
|
|
|
|
dbg_msg("joystick", "%d joystick(s) found", NumJoysticks);
|
|
|
|
int ActualIndex = 0;
|
|
|
|
for(int i = 0; i < NumJoysticks; i++)
|
|
|
|
{
|
|
|
|
SDL_Joystick *pJoystick = SDL_JoystickOpen(i);
|
|
|
|
if(!pJoystick)
|
|
|
|
{
|
|
|
|
dbg_msg("joystick", "Could not open joystick %d: '%s'", i, SDL_GetError());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
m_vJoysticks.emplace_back(this, ActualIndex, pJoystick);
|
|
|
|
const CJoystick &Joystick = m_vJoysticks[m_vJoysticks.size() - 1];
|
|
|
|
dbg_msg("joystick", "Opened Joystick %d '%s' (%d axes, %d buttons, %d balls, %d hats)", i, Joystick.GetName(),
|
|
|
|
Joystick.GetNumAxes(), Joystick.GetNumButtons(), Joystick.GetNumBalls(), Joystick.GetNumHats());
|
|
|
|
ActualIndex++;
|
|
|
|
}
|
|
|
|
if(ActualIndex > 0)
|
|
|
|
{
|
|
|
|
UpdateActiveJoystick();
|
|
|
|
Console()->Chain("joystick_guid", ConchainJoystickGuidChanged, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dbg_msg("joystick", "No joysticks found");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CInput::UpdateActiveJoystick()
|
|
|
|
{
|
|
|
|
if(m_vJoysticks.empty())
|
|
|
|
return;
|
|
|
|
m_pActiveJoystick = nullptr;
|
|
|
|
for(auto &Joystick : m_vJoysticks)
|
|
|
|
{
|
2022-06-15 11:00:27 +00:00
|
|
|
if(str_comp(Joystick.GetGUID(), g_Config.m_InpControllerGUID) == 0)
|
2022-06-06 19:19:08 +00:00
|
|
|
{
|
|
|
|
m_pActiveJoystick = &Joystick;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Fall back to first joystick if no match was found
|
|
|
|
if(!m_pActiveJoystick)
|
|
|
|
m_pActiveJoystick = &m_vJoysticks[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
void CInput::ConchainJoystickGuidChanged(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
|
|
|
{
|
|
|
|
pfnCallback(pResult, pCallbackUserData);
|
|
|
|
static_cast<CInput *>(pUserData)->UpdateActiveJoystick();
|
|
|
|
}
|
|
|
|
|
|
|
|
float CInput::GetJoystickDeadzone()
|
|
|
|
{
|
2022-06-15 11:00:27 +00:00
|
|
|
return g_Config.m_InpControllerTolerance / 50.0f;
|
2022-06-06 19:19:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CInput::CJoystick::CJoystick(CInput *pInput, int Index, SDL_Joystick *pDelegate)
|
|
|
|
{
|
|
|
|
m_pInput = pInput;
|
|
|
|
m_Index = Index;
|
|
|
|
m_pDelegate = pDelegate;
|
|
|
|
m_NumAxes = SDL_JoystickNumAxes(pDelegate);
|
|
|
|
m_NumButtons = SDL_JoystickNumButtons(pDelegate);
|
|
|
|
m_NumBalls = SDL_JoystickNumBalls(pDelegate);
|
|
|
|
m_NumHats = SDL_JoystickNumHats(pDelegate);
|
|
|
|
str_copy(m_aName, SDL_JoystickName(pDelegate), sizeof(m_aName));
|
|
|
|
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(pDelegate), m_aGUID, sizeof(m_aGUID));
|
|
|
|
m_InstanceID = SDL_JoystickInstanceID(pDelegate);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CInput::CloseJoysticks()
|
|
|
|
{
|
2022-06-18 09:57:57 +00:00
|
|
|
if(SDL_WasInit(SDL_INIT_JOYSTICK))
|
|
|
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
|
|
|
|
2022-06-06 19:19:08 +00:00
|
|
|
m_vJoysticks.clear();
|
|
|
|
m_pActiveJoystick = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CInput::SelectNextJoystick()
|
|
|
|
{
|
|
|
|
const int Num = m_vJoysticks.size();
|
|
|
|
if(Num > 1)
|
|
|
|
{
|
|
|
|
m_pActiveJoystick = &m_vJoysticks[(m_pActiveJoystick->GetIndex() + 1) % Num];
|
2022-06-15 11:00:27 +00:00
|
|
|
str_copy(g_Config.m_InpControllerGUID, m_pActiveJoystick->GetGUID(), sizeof(g_Config.m_InpControllerGUID));
|
2022-06-06 19:19:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float CInput::CJoystick::GetAxisValue(int Axis)
|
|
|
|
{
|
|
|
|
return (SDL_JoystickGetAxis(m_pDelegate, Axis) - SDL_JOYSTICK_AXIS_MIN) / float(SDL_JOYSTICK_AXIS_MAX - SDL_JOYSTICK_AXIS_MIN) * 2.0f - 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CInput::CJoystick::GetJoystickHatKey(int Hat, int HatValue)
|
|
|
|
{
|
|
|
|
switch(HatValue)
|
|
|
|
{
|
|
|
|
case SDL_HAT_LEFTUP: return KEY_JOY_HAT0_LEFTUP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
|
|
|
|
case SDL_HAT_UP: return KEY_JOY_HAT0_UP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
|
|
|
|
case SDL_HAT_RIGHTUP: return KEY_JOY_HAT0_RIGHTUP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
|
|
|
|
case SDL_HAT_LEFT: return KEY_JOY_HAT0_LEFT + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
|
|
|
|
case SDL_HAT_RIGHT: return KEY_JOY_HAT0_RIGHT + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
|
|
|
|
case SDL_HAT_LEFTDOWN: return KEY_JOY_HAT0_LEFTDOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
|
|
|
|
case SDL_HAT_DOWN: return KEY_JOY_HAT0_DOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
|
|
|
|
case SDL_HAT_RIGHTDOWN: return KEY_JOY_HAT0_RIGHTDOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CInput::CJoystick::GetHatValue(int Hat)
|
|
|
|
{
|
|
|
|
return GetJoystickHatKey(Hat, SDL_JoystickGetHat(m_pDelegate, Hat));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CInput::CJoystick::Relative(float *pX, float *pY)
|
|
|
|
{
|
2022-06-15 11:00:27 +00:00
|
|
|
if(!g_Config.m_InpControllerEnable)
|
2022-06-06 19:19:08 +00:00
|
|
|
return false;
|
|
|
|
|
2022-06-15 11:00:27 +00:00
|
|
|
const vec2 RawJoystickPos = vec2(GetAxisValue(g_Config.m_InpControllerX), GetAxisValue(g_Config.m_InpControllerY));
|
2022-06-06 19:19:08 +00:00
|
|
|
const float Len = length(RawJoystickPos);
|
|
|
|
const float DeadZone = Input()->GetJoystickDeadzone();
|
|
|
|
if(Len > DeadZone)
|
|
|
|
{
|
|
|
|
const float Factor = 0.1f * maximum((Len - DeadZone) / (1 - DeadZone), 0.001f) / Len;
|
|
|
|
*pX = RawJoystickPos.x * Factor;
|
|
|
|
*pY = RawJoystickPos.y * Factor;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CInput::CJoystick::Absolute(float *pX, float *pY)
|
|
|
|
{
|
2022-06-15 11:00:27 +00:00
|
|
|
if(!Input()->m_MouseFocus || !Input()->m_InputGrabbed || !g_Config.m_InpControllerEnable)
|
2022-06-06 19:19:08 +00:00
|
|
|
return false;
|
|
|
|
|
2022-06-15 11:00:27 +00:00
|
|
|
const vec2 RawJoystickPos = vec2(GetAxisValue(g_Config.m_InpControllerX), GetAxisValue(g_Config.m_InpControllerY));
|
2022-06-06 19:19:08 +00:00
|
|
|
const float DeadZone = Input()->GetJoystickDeadzone();
|
|
|
|
if(dot(RawJoystickPos, RawJoystickPos) > DeadZone * DeadZone)
|
|
|
|
{
|
|
|
|
*pX = RawJoystickPos.x;
|
|
|
|
*pY = RawJoystickPos.y;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2022-06-06 18:10:46 +00:00
|
|
|
bool CInput::MouseRelative(float *pX, float *pY)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2021-10-23 11:48:21 +00:00
|
|
|
if(!m_MouseFocus || !m_InputGrabbed)
|
2022-06-06 18:10:46 +00:00
|
|
|
return false;
|
2016-05-01 12:00:53 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int nx = 0, ny = 0;
|
2021-08-24 10:18:20 +00:00
|
|
|
#if defined(CONF_PLATFORM_ANDROID) // No relative mouse on Android
|
2022-06-06 18:19:13 +00:00
|
|
|
static int s_LastX = 0;
|
|
|
|
static int s_LastY = 0;
|
2021-08-24 10:18:20 +00:00
|
|
|
SDL_GetMouseState(&nx, &ny);
|
2022-06-06 18:19:13 +00:00
|
|
|
int XTmp = nx - s_LastX;
|
|
|
|
int YTmp = ny - s_LastY;
|
|
|
|
s_LastX = nx;
|
|
|
|
s_LastY = ny;
|
2021-08-24 10:18:20 +00:00
|
|
|
nx = XTmp;
|
|
|
|
ny = YTmp;
|
|
|
|
#else
|
2020-09-22 16:02:03 +00:00
|
|
|
SDL_GetRelativeMouseState(&nx, &ny);
|
2021-08-24 10:18:20 +00:00
|
|
|
#endif
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2022-06-06 20:03:24 +00:00
|
|
|
*pX = nx;
|
|
|
|
*pY = ny;
|
2022-06-06 18:10:46 +00:00
|
|
|
return *pX != 0.0f || *pY != 0.0f;
|
2021-09-15 21:52:09 +00:00
|
|
|
}
|
|
|
|
|
2021-10-23 11:48:21 +00:00
|
|
|
void CInput::MouseModeAbsolute()
|
2021-09-15 21:52:09 +00:00
|
|
|
{
|
2021-10-23 11:48:21 +00:00
|
|
|
m_InputGrabbed = 0;
|
|
|
|
SDL_SetRelativeMouseMode(SDL_FALSE);
|
|
|
|
Graphics()->SetWindowGrab(false);
|
2021-09-15 21:52:09 +00:00
|
|
|
}
|
|
|
|
|
2021-10-23 11:48:21 +00:00
|
|
|
void CInput::MouseModeRelative()
|
2021-09-15 21:52:09 +00:00
|
|
|
{
|
2021-10-23 11:48:21 +00:00
|
|
|
m_InputGrabbed = 1;
|
|
|
|
#if !defined(CONF_PLATFORM_ANDROID) // No relative mouse on Android
|
2021-09-15 21:52:09 +00:00
|
|
|
SDL_SetRelativeMouseMode(SDL_TRUE);
|
2021-10-23 11:48:21 +00:00
|
|
|
#endif
|
2015-08-24 23:01:38 +00:00
|
|
|
Graphics()->SetWindowGrab(true);
|
2021-10-23 11:48:21 +00:00
|
|
|
// Clear pending relative mouse motion
|
2021-06-25 12:51:21 +00:00
|
|
|
SDL_GetRelativeMouseState(0x0, 0x0);
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2022-06-06 17:58:03 +00:00
|
|
|
void CInput::NativeMousePos(int *pX, int *pY) const
|
2021-09-12 17:32:00 +00:00
|
|
|
{
|
2022-06-06 17:58:03 +00:00
|
|
|
SDL_GetMouseState(pX, pY);
|
2021-09-12 17:32:00 +00:00
|
|
|
}
|
|
|
|
|
2022-06-06 17:58:03 +00:00
|
|
|
bool CInput::NativeMousePressed(int Index)
|
2021-09-12 17:32:00 +00:00
|
|
|
{
|
|
|
|
int i = SDL_GetMouseState(NULL, NULL);
|
2022-06-06 17:58:03 +00:00
|
|
|
return (i & SDL_BUTTON(Index)) != 0;
|
2021-09-12 17:32:00 +00:00
|
|
|
}
|
|
|
|
|
2022-01-16 11:18:23 +00:00
|
|
|
bool CInput::MouseDoubleClick()
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2019-01-06 09:23:25 +00:00
|
|
|
if(m_MouseDoubleClick)
|
2010-09-03 17:39:20 +00:00
|
|
|
{
|
2019-01-06 09:23:25 +00:00
|
|
|
m_MouseDoubleClick = false;
|
2022-01-16 11:18:23 +00:00
|
|
|
return true;
|
2010-09-03 17:39:20 +00:00
|
|
|
}
|
2022-01-16 11:18:23 +00:00
|
|
|
return false;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2020-09-22 16:02:03 +00:00
|
|
|
const char *CInput::GetClipboardText()
|
2015-08-25 12:24:46 +00:00
|
|
|
{
|
2022-03-01 22:19:49 +00:00
|
|
|
SDL_free(m_pClipboardText);
|
2015-08-25 12:24:46 +00:00
|
|
|
m_pClipboardText = SDL_GetClipboardText();
|
|
|
|
return m_pClipboardText;
|
|
|
|
}
|
|
|
|
|
2022-06-06 17:58:03 +00:00
|
|
|
void CInput::SetClipboardText(const char *pText)
|
2015-08-25 12:24:46 +00:00
|
|
|
{
|
2022-06-06 17:58:03 +00:00
|
|
|
SDL_SetClipboardText(pText);
|
2015-08-25 12:24:46 +00:00
|
|
|
}
|
|
|
|
|
2016-04-30 18:11:26 +00:00
|
|
|
void CInput::Clear()
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
|
|
|
mem_zero(m_aInputState, sizeof(m_aInputState));
|
|
|
|
mem_zero(m_aInputCount, sizeof(m_aInputCount));
|
2016-04-30 18:11:26 +00:00
|
|
|
m_NumEvents = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2016-04-30 18:11:26 +00:00
|
|
|
bool CInput::KeyState(int Key) const
|
2016-04-29 19:51:54 +00:00
|
|
|
{
|
2017-07-21 17:53:49 +00:00
|
|
|
if(Key < 0 || Key >= KEY_LAST)
|
|
|
|
return false;
|
|
|
|
return m_aInputState[Key];
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2022-06-06 18:18:33 +00:00
|
|
|
void CInput::UpdateMouseState()
|
|
|
|
{
|
|
|
|
const int MouseState = SDL_GetMouseState(NULL, NULL);
|
|
|
|
if(MouseState & SDL_BUTTON(SDL_BUTTON_LEFT))
|
|
|
|
m_aInputState[KEY_MOUSE_1] = 1;
|
|
|
|
if(MouseState & SDL_BUTTON(SDL_BUTTON_RIGHT))
|
|
|
|
m_aInputState[KEY_MOUSE_2] = 1;
|
|
|
|
if(MouseState & SDL_BUTTON(SDL_BUTTON_MIDDLE))
|
|
|
|
m_aInputState[KEY_MOUSE_3] = 1;
|
|
|
|
if(MouseState & SDL_BUTTON(SDL_BUTTON_X1))
|
|
|
|
m_aInputState[KEY_MOUSE_4] = 1;
|
|
|
|
if(MouseState & SDL_BUTTON(SDL_BUTTON_X2))
|
|
|
|
m_aInputState[KEY_MOUSE_5] = 1;
|
|
|
|
if(MouseState & SDL_BUTTON(6))
|
|
|
|
m_aInputState[KEY_MOUSE_6] = 1;
|
|
|
|
if(MouseState & SDL_BUTTON(7))
|
|
|
|
m_aInputState[KEY_MOUSE_7] = 1;
|
|
|
|
if(MouseState & SDL_BUTTON(8))
|
|
|
|
m_aInputState[KEY_MOUSE_8] = 1;
|
|
|
|
if(MouseState & SDL_BUTTON(9))
|
|
|
|
m_aInputState[KEY_MOUSE_9] = 1;
|
|
|
|
}
|
|
|
|
|
2022-06-06 19:19:08 +00:00
|
|
|
void CInput::UpdateJoystickState()
|
|
|
|
{
|
2022-06-15 11:00:27 +00:00
|
|
|
if(!g_Config.m_InpControllerEnable)
|
2022-06-06 19:19:08 +00:00
|
|
|
return;
|
|
|
|
IJoystick *pJoystick = GetActiveJoystick();
|
|
|
|
if(!pJoystick)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const float DeadZone = GetJoystickDeadzone();
|
|
|
|
for(int Axis = 0; Axis < pJoystick->GetNumAxes(); Axis++)
|
|
|
|
{
|
|
|
|
const float Value = pJoystick->GetAxisValue(Axis);
|
|
|
|
const int LeftKey = KEY_JOY_AXIS_0_LEFT + 2 * Axis;
|
|
|
|
const int RightKey = LeftKey + 1;
|
|
|
|
m_aInputState[LeftKey] = Value <= -DeadZone;
|
|
|
|
m_aInputState[RightKey] = Value >= DeadZone;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int Hat = 0; Hat < pJoystick->GetNumHats(); Hat++)
|
|
|
|
{
|
|
|
|
const int HatState = pJoystick->GetHatValue(Hat);
|
|
|
|
for(int Key = KEY_JOY_HAT0_LEFTUP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key <= KEY_JOY_HAT0_RIGHTDOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key++)
|
|
|
|
m_aInputState[Key] = Key == HatState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CInput::HandleJoystickAxisMotionEvent(const SDL_Event &Event)
|
|
|
|
{
|
2022-06-15 11:00:27 +00:00
|
|
|
if(!g_Config.m_InpControllerEnable)
|
2022-06-06 19:19:08 +00:00
|
|
|
return;
|
|
|
|
CJoystick *pJoystick = GetActiveJoystick();
|
|
|
|
if(!pJoystick || pJoystick->GetInstanceID() != Event.jaxis.which)
|
|
|
|
return;
|
|
|
|
if(Event.jaxis.axis >= NUM_JOYSTICK_AXES)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const int LeftKey = KEY_JOY_AXIS_0_LEFT + 2 * Event.jaxis.axis;
|
|
|
|
const int RightKey = LeftKey + 1;
|
|
|
|
const float DeadZone = GetJoystickDeadzone();
|
|
|
|
|
|
|
|
if(Event.jaxis.value <= SDL_JOYSTICK_AXIS_MIN * DeadZone && !m_aInputState[LeftKey])
|
|
|
|
{
|
|
|
|
m_aInputState[LeftKey] = true;
|
|
|
|
m_aInputCount[LeftKey] = m_InputCounter;
|
|
|
|
AddEvent(0, LeftKey, IInput::FLAG_PRESS);
|
|
|
|
}
|
|
|
|
else if(Event.jaxis.value > SDL_JOYSTICK_AXIS_MIN * DeadZone && m_aInputState[LeftKey])
|
|
|
|
{
|
|
|
|
m_aInputState[LeftKey] = false;
|
|
|
|
AddEvent(0, LeftKey, IInput::FLAG_RELEASE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Event.jaxis.value >= SDL_JOYSTICK_AXIS_MAX * DeadZone && !m_aInputState[RightKey])
|
|
|
|
{
|
|
|
|
m_aInputState[RightKey] = true;
|
|
|
|
m_aInputCount[RightKey] = m_InputCounter;
|
|
|
|
AddEvent(0, RightKey, IInput::FLAG_PRESS);
|
|
|
|
}
|
|
|
|
else if(Event.jaxis.value < SDL_JOYSTICK_AXIS_MAX * DeadZone && m_aInputState[RightKey])
|
|
|
|
{
|
|
|
|
m_aInputState[RightKey] = false;
|
|
|
|
AddEvent(0, RightKey, IInput::FLAG_RELEASE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CInput::HandleJoystickButtonEvent(const SDL_Event &Event)
|
|
|
|
{
|
2022-06-15 11:00:27 +00:00
|
|
|
if(!g_Config.m_InpControllerEnable)
|
2022-06-06 19:19:08 +00:00
|
|
|
return;
|
|
|
|
CJoystick *pJoystick = GetActiveJoystick();
|
|
|
|
if(!pJoystick || pJoystick->GetInstanceID() != Event.jbutton.which)
|
|
|
|
return;
|
|
|
|
if(Event.jbutton.button >= NUM_JOYSTICK_BUTTONS)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const int Key = Event.jbutton.button + KEY_JOYSTICK_BUTTON_0;
|
|
|
|
|
|
|
|
if(Event.type == SDL_JOYBUTTONDOWN)
|
|
|
|
{
|
|
|
|
m_aInputState[Key] = true;
|
|
|
|
m_aInputCount[Key] = m_InputCounter;
|
|
|
|
AddEvent(0, Key, IInput::FLAG_PRESS);
|
|
|
|
}
|
|
|
|
else if(Event.type == SDL_JOYBUTTONUP)
|
|
|
|
{
|
|
|
|
m_aInputState[Key] = false;
|
|
|
|
AddEvent(0, Key, IInput::FLAG_RELEASE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CInput::HandleJoystickHatMotionEvent(const SDL_Event &Event)
|
|
|
|
{
|
2022-06-15 11:00:27 +00:00
|
|
|
if(!g_Config.m_InpControllerEnable)
|
2022-06-06 19:19:08 +00:00
|
|
|
return;
|
|
|
|
CJoystick *pJoystick = GetActiveJoystick();
|
|
|
|
if(!pJoystick || pJoystick->GetInstanceID() != Event.jhat.which)
|
|
|
|
return;
|
|
|
|
if(Event.jhat.hat >= NUM_JOYSTICK_HATS)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const int CurrentKey = CJoystick::GetJoystickHatKey(Event.jhat.hat, Event.jhat.value);
|
|
|
|
|
|
|
|
for(int Key = KEY_JOY_HAT0_LEFTUP + Event.jhat.hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key <= KEY_JOY_HAT0_RIGHTDOWN + Event.jhat.hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key++)
|
|
|
|
{
|
|
|
|
if(Key != CurrentKey && m_aInputState[Key])
|
|
|
|
{
|
|
|
|
m_aInputState[Key] = false;
|
|
|
|
AddEvent(0, Key, IInput::FLAG_RELEASE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(CurrentKey >= 0)
|
|
|
|
{
|
|
|
|
m_aInputState[CurrentKey] = true;
|
|
|
|
m_aInputCount[CurrentKey] = m_InputCounter;
|
|
|
|
AddEvent(0, CurrentKey, IInput::FLAG_PRESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-15 05:16:06 +00:00
|
|
|
bool CInput::GetIMEState()
|
|
|
|
{
|
2020-10-25 15:48:12 +00:00
|
|
|
return m_NumTextInputInstances > 0;
|
2016-08-15 05:16:06 +00:00
|
|
|
}
|
|
|
|
|
2017-07-15 13:25:36 +00:00
|
|
|
void CInput::SetIMEState(bool Activate)
|
2016-08-15 04:01:31 +00:00
|
|
|
{
|
2017-07-15 13:25:36 +00:00
|
|
|
if(Activate)
|
|
|
|
{
|
2020-10-25 15:48:12 +00:00
|
|
|
if(m_NumTextInputInstances == 0)
|
2017-07-15 13:25:36 +00:00
|
|
|
SDL_StartTextInput();
|
2020-10-25 15:48:12 +00:00
|
|
|
m_NumTextInputInstances++;
|
2017-07-15 13:25:36 +00:00
|
|
|
}
|
2016-08-15 04:01:31 +00:00
|
|
|
else
|
|
|
|
{
|
2020-10-25 15:48:12 +00:00
|
|
|
if(m_NumTextInputInstances == 0)
|
2017-07-15 13:25:36 +00:00
|
|
|
return;
|
2020-10-25 15:48:12 +00:00
|
|
|
m_NumTextInputInstances--;
|
|
|
|
if(m_NumTextInputInstances == 0)
|
2017-07-15 13:25:36 +00:00
|
|
|
SDL_StopTextInput();
|
2016-08-15 04:01:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-25 15:48:12 +00:00
|
|
|
const char *CInput::GetIMEEditingText()
|
2016-08-15 04:01:31 +00:00
|
|
|
{
|
2020-09-22 16:01:13 +00:00
|
|
|
if(m_EditingTextLen > 0)
|
2017-07-26 01:58:00 +00:00
|
|
|
return m_aEditingText;
|
2016-08-15 04:01:31 +00:00
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
int CInput::GetEditingCursor()
|
|
|
|
{
|
|
|
|
return m_EditingCursor;
|
|
|
|
}
|
|
|
|
|
2020-09-22 16:01:13 +00:00
|
|
|
void CInput::SetEditingPosition(float X, float Y)
|
|
|
|
{
|
|
|
|
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
|
|
|
int ScreenWidth = Graphics()->ScreenWidth();
|
|
|
|
int ScreenHeight = Graphics()->ScreenHeight();
|
|
|
|
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
|
|
|
|
2020-09-22 16:02:03 +00:00
|
|
|
vec2 ScreenScale = vec2(ScreenWidth / (ScreenX1 - ScreenX0), ScreenHeight / (ScreenY1 - ScreenY0));
|
2020-09-22 16:01:13 +00:00
|
|
|
|
|
|
|
SDL_Rect ImeWindowRect;
|
|
|
|
ImeWindowRect.x = X * ScreenScale.x;
|
|
|
|
ImeWindowRect.y = Y * ScreenScale.y;
|
|
|
|
ImeWindowRect.h = 60;
|
|
|
|
ImeWindowRect.w = 1000;
|
|
|
|
|
|
|
|
SDL_SetTextInputRect(&ImeWindowRect);
|
|
|
|
}
|
|
|
|
|
2010-12-11 21:04:50 +00:00
|
|
|
int CInput::Update()
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2016-04-30 18:11:26 +00:00
|
|
|
// keep the counter between 1..0xFFFF, 0 means not pressed
|
2020-09-22 16:02:03 +00:00
|
|
|
m_InputCounter = (m_InputCounter % 0xFFFF) + 1;
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2022-01-16 10:52:04 +00:00
|
|
|
int NumKeyStates;
|
|
|
|
const Uint8 *pState = SDL_GetKeyboardState(&NumKeyStates);
|
|
|
|
if(NumKeyStates >= KEY_MOUSE_1)
|
|
|
|
NumKeyStates = KEY_MOUSE_1;
|
|
|
|
mem_copy(m_aInputState, pState, NumKeyStates);
|
|
|
|
mem_zero(m_aInputState + NumKeyStates, KEY_LAST - NumKeyStates);
|
|
|
|
if(m_EditingTextLen == 0)
|
|
|
|
m_EditingTextLen = -1;
|
2022-01-16 10:41:02 +00:00
|
|
|
|
2022-06-06 18:18:33 +00:00
|
|
|
// these states must always be updated manually because they are not in the SDL_GetKeyboardState from SDL
|
|
|
|
UpdateMouseState();
|
2022-06-06 19:19:08 +00:00
|
|
|
UpdateJoystickState();
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2022-01-16 10:55:02 +00:00
|
|
|
SDL_Event Event;
|
|
|
|
bool IgnoreKeys = false;
|
|
|
|
while(SDL_PollEvent(&Event))
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2022-01-16 10:55:02 +00:00
|
|
|
int Scancode = 0;
|
|
|
|
int Action = IInput::FLAG_PRESS;
|
|
|
|
switch(Event.type)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2022-01-16 10:55:02 +00:00
|
|
|
case SDL_TEXTEDITING:
|
|
|
|
{
|
|
|
|
m_EditingTextLen = str_length(Event.edit.text);
|
|
|
|
if(m_EditingTextLen)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2022-01-16 10:55:02 +00:00
|
|
|
str_copy(m_aEditingText, Event.edit.text, sizeof(m_aEditingText));
|
|
|
|
m_EditingCursor = 0;
|
|
|
|
for(int i = 0; i < Event.edit.start; i++)
|
|
|
|
m_EditingCursor = str_utf8_forward(m_aEditingText, m_EditingCursor);
|
|
|
|
}
|
|
|
|
else
|
2020-09-22 16:02:03 +00:00
|
|
|
{
|
2022-01-16 10:55:02 +00:00
|
|
|
m_aEditingText[0] = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_TEXTINPUT:
|
|
|
|
m_EditingTextLen = -1;
|
|
|
|
AddEvent(Event.text.text, 0, IInput::FLAG_TEXT);
|
|
|
|
break;
|
|
|
|
// handle keys
|
|
|
|
case SDL_KEYDOWN:
|
|
|
|
// See SDL_Keymod for possible modifiers:
|
|
|
|
// NONE = 0
|
|
|
|
// LSHIFT = 1
|
|
|
|
// RSHIFT = 2
|
|
|
|
// LCTRL = 64
|
|
|
|
// RCTRL = 128
|
|
|
|
// LALT = 256
|
|
|
|
// RALT = 512
|
|
|
|
// LGUI = 1024
|
|
|
|
// RGUI = 2048
|
|
|
|
// NUM = 4096
|
|
|
|
// CAPS = 8192
|
|
|
|
// MODE = 16384
|
|
|
|
// Sum if you want to ignore multiple modifiers.
|
|
|
|
if(!(Event.key.keysym.mod & g_Config.m_InpIgnoredModifiers))
|
|
|
|
{
|
|
|
|
Scancode = g_Config.m_InpTranslatedKeys ? SDL_GetScancodeFromKey(Event.key.keysym.sym) : Event.key.keysym.scancode;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SDL_KEYUP:
|
|
|
|
Action = IInput::FLAG_RELEASE;
|
|
|
|
Scancode = g_Config.m_InpTranslatedKeys ? SDL_GetScancodeFromKey(Event.key.keysym.sym) : Event.key.keysym.scancode;
|
|
|
|
break;
|
|
|
|
|
2022-06-06 19:19:08 +00:00
|
|
|
// handle the joystick events
|
|
|
|
case SDL_JOYAXISMOTION:
|
|
|
|
HandleJoystickAxisMotionEvent(Event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SDL_JOYBUTTONUP:
|
|
|
|
case SDL_JOYBUTTONDOWN:
|
|
|
|
HandleJoystickButtonEvent(Event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SDL_JOYHATMOTION:
|
|
|
|
HandleJoystickHatMotionEvent(Event);
|
|
|
|
break;
|
|
|
|
|
2022-01-16 10:55:02 +00:00
|
|
|
// handle mouse buttons
|
|
|
|
case SDL_MOUSEBUTTONUP:
|
|
|
|
Action = IInput::FLAG_RELEASE;
|
|
|
|
|
2022-06-25 13:21:44 +00:00
|
|
|
[[fallthrough]];
|
2022-01-16 10:55:02 +00:00
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
|
|
if(Event.button.button == SDL_BUTTON_LEFT)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_1;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.button.button == SDL_BUTTON_RIGHT)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_2;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.button.button == SDL_BUTTON_MIDDLE)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_3;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.button.button == SDL_BUTTON_X1)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_4;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.button.button == SDL_BUTTON_X2)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_5;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.button.button == 6)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_6;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.button.button == 7)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_7;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.button.button == 8)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_8;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.button.button == 9)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_9;
|
2019-02-04 16:06:32 +00:00
|
|
|
if(Event.button.button == SDL_BUTTON_LEFT)
|
|
|
|
{
|
|
|
|
if(Event.button.clicks % 2 == 0)
|
|
|
|
m_MouseDoubleClick = true;
|
|
|
|
if(Event.button.clicks == 1)
|
|
|
|
m_MouseDoubleClick = false;
|
|
|
|
}
|
2022-01-16 10:55:02 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SDL_MOUSEWHEEL:
|
|
|
|
if(Event.wheel.y > 0)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_WHEEL_UP;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.wheel.y < 0)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_WHEEL_DOWN;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.wheel.x > 0)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_WHEEL_LEFT;
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Event.wheel.x < 0)
|
2022-02-16 19:54:11 +00:00
|
|
|
Scancode = KEY_MOUSE_WHEEL_RIGHT;
|
2022-01-16 10:55:02 +00:00
|
|
|
Action |= IInput::FLAG_RELEASE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SDL_WINDOWEVENT:
|
|
|
|
// Ignore keys following a focus gain as they may be part of global
|
|
|
|
// shortcuts
|
|
|
|
switch(Event.window.event)
|
|
|
|
{
|
|
|
|
case SDL_WINDOWEVENT_MOVED:
|
|
|
|
Graphics()->Move(Event.window.data1, Event.window.data2);
|
|
|
|
break;
|
|
|
|
// listen to size changes, this includes our manual changes and the ones by the window manager
|
|
|
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
|
|
|
Graphics()->GotResized(Event.window.data1, Event.window.data2, -1);
|
2020-09-22 16:02:03 +00:00
|
|
|
break;
|
2022-01-16 10:55:02 +00:00
|
|
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
|
|
|
if(m_InputGrabbed)
|
2020-09-22 16:02:03 +00:00
|
|
|
{
|
2022-01-16 10:55:02 +00:00
|
|
|
// Enable this in case SDL 2.0.16 has major bugs or 2.0.18 still doesn't fix tabbing out with relative mouse
|
|
|
|
// MouseModeRelative();
|
|
|
|
// Clear pending relative mouse motion
|
|
|
|
SDL_GetRelativeMouseState(0x0, 0x0);
|
2020-09-22 16:02:03 +00:00
|
|
|
}
|
2022-01-16 10:55:02 +00:00
|
|
|
m_MouseFocus = true;
|
|
|
|
IgnoreKeys = true;
|
2020-09-22 16:02:03 +00:00
|
|
|
break;
|
2022-01-16 10:55:02 +00:00
|
|
|
case SDL_WINDOWEVENT_FOCUS_LOST:
|
|
|
|
m_MouseFocus = false;
|
|
|
|
IgnoreKeys = true;
|
|
|
|
if(m_InputGrabbed)
|
2020-09-22 16:02:03 +00:00
|
|
|
{
|
2022-01-16 10:55:02 +00:00
|
|
|
// Enable this in case SDL 2.0.16 has major bugs or 2.0.18 still doesn't fix tabbing out with relative mouse
|
|
|
|
// MouseModeAbsolute();
|
|
|
|
// Remember that we had relative mouse
|
|
|
|
m_InputGrabbed = true;
|
2020-09-22 16:02:03 +00:00
|
|
|
}
|
|
|
|
break;
|
2022-01-16 10:55:02 +00:00
|
|
|
case SDL_WINDOWEVENT_MINIMIZED:
|
|
|
|
Graphics()->WindowDestroyNtf(Event.window.windowID);
|
2020-09-22 16:02:03 +00:00
|
|
|
break;
|
|
|
|
|
2022-01-16 10:55:02 +00:00
|
|
|
case SDL_WINDOWEVENT_MAXIMIZED:
|
2021-10-23 11:48:21 +00:00
|
|
|
#if defined(CONF_PLATFORM_MACOS) // Todo: remove this when fixed in SDL
|
2022-01-16 10:55:02 +00:00
|
|
|
MouseModeAbsolute();
|
|
|
|
MouseModeRelative();
|
2021-10-23 11:48:21 +00:00
|
|
|
#endif
|
2022-06-25 13:21:44 +00:00
|
|
|
[[fallthrough]];
|
2022-01-16 10:55:02 +00:00
|
|
|
case SDL_WINDOWEVENT_RESTORED:
|
|
|
|
Graphics()->WindowCreateNtf(Event.window.windowID);
|
2020-09-22 16:02:03 +00:00
|
|
|
break;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
2022-01-16 10:55:02 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// other messages
|
|
|
|
case SDL_QUIT:
|
|
|
|
return 1;
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2022-01-16 10:55:02 +00:00
|
|
|
if(Scancode > KEY_FIRST && Scancode < g_MaxKeys && !IgnoreKeys && (!SDL_IsTextInputActive() || m_EditingTextLen == -1))
|
|
|
|
{
|
|
|
|
if(Action & IInput::FLAG_PRESS)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2022-01-16 10:55:02 +00:00
|
|
|
m_aInputState[Scancode] = 1;
|
|
|
|
m_aInputCount[Scancode] = m_InputCounter;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
2022-01-16 10:55:02 +00:00
|
|
|
AddEvent(0, Scancode, Action);
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
}
|
2010-12-11 21:04:50 +00:00
|
|
|
|
|
|
|
return 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2014-06-16 11:29:18 +00:00
|
|
|
int CInput::VideoRestartNeeded()
|
|
|
|
{
|
2020-09-22 16:02:03 +00:00
|
|
|
if(m_VideoRestartNeeded)
|
2014-06-16 11:29:18 +00:00
|
|
|
{
|
|
|
|
m_VideoRestartNeeded = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2020-09-22 16:02:03 +00:00
|
|
|
IEngineInput *CreateEngineInput()
|
|
|
|
{
|
|
|
|
return new CInput;
|
|
|
|
}
|