mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-18 05:58:19 +00:00
Merge pull request #8685 from Robyt3/Client-Binds-Fixes
Support composite binds with `+` commands, fix handling of composite binds with F1-F24 keys, fix incorrect key names with multiple modifiers, refactoring
This commit is contained in:
commit
8d609b9202
|
@ -367,6 +367,26 @@ bool CInput::KeyState(int Key) const
|
|||
return m_aInputState[Key];
|
||||
}
|
||||
|
||||
int CInput::FindKeyByName(const char *pKeyName) const
|
||||
{
|
||||
// check for numeric
|
||||
if(pKeyName[0] == '&')
|
||||
{
|
||||
int Key = str_toint(pKeyName + 1);
|
||||
if(Key > KEY_FIRST && Key < KEY_LAST)
|
||||
return Key; // numeric
|
||||
}
|
||||
|
||||
// search for key
|
||||
for(int Key = KEY_FIRST; Key < KEY_LAST; Key++)
|
||||
{
|
||||
if(str_comp_nocase(pKeyName, KeyName(Key)) == 0)
|
||||
return Key;
|
||||
}
|
||||
|
||||
return KEY_UNKNOWN;
|
||||
}
|
||||
|
||||
void CInput::UpdateMouseState()
|
||||
{
|
||||
const int MouseState = SDL_GetMouseState(nullptr, nullptr);
|
||||
|
|
|
@ -136,6 +136,7 @@ public:
|
|||
bool AltIsPressed() const override { return KeyState(KEY_LALT) || KeyState(KEY_RALT); }
|
||||
bool KeyIsPressed(int Key) const override { return KeyState(Key); }
|
||||
bool KeyPress(int Key, bool CheckCounter) const override { return CheckCounter ? (m_aInputCount[Key] == m_InputCounter) : m_aInputCount[Key]; }
|
||||
int FindKeyByName(const char *pKeyName) const override;
|
||||
|
||||
size_t NumJoysticks() const override { return m_vJoysticks.size(); }
|
||||
CJoystick *GetJoystick(size_t Index) override { return &m_vJoysticks[Index]; }
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
virtual bool KeyIsPressed(int Key) const = 0;
|
||||
virtual bool KeyPress(int Key, bool CheckCounter = false) const = 0;
|
||||
const char *KeyName(int Key) const { return (Key >= 0 && Key < g_MaxKeys) ? g_aaKeyStrings[Key] : g_aaKeyStrings[0]; }
|
||||
virtual int FindKeyByName(const char *pKeyName) const = 0;
|
||||
|
||||
// joystick
|
||||
class IJoystick
|
||||
|
|
|
@ -11,26 +11,15 @@ static const ColorRGBA gs_BindPrintColor{1.0f, 1.0f, 0.8f, 1.0f};
|
|||
|
||||
bool CBinds::CBindsSpecial::OnInput(const IInput::CEvent &Event)
|
||||
{
|
||||
if((Event.m_Flags & (IInput::FLAG_PRESS | IInput::FLAG_RELEASE)) == 0)
|
||||
return false;
|
||||
|
||||
// only handle F and composed F binds
|
||||
if(((Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F12) || (Event.m_Key >= KEY_F13 && Event.m_Key <= KEY_F24)) && (Event.m_Key != KEY_F5 || !m_pClient->m_Menus.IsActive()))
|
||||
// do not handle F5 bind while menu is active
|
||||
if(((Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F12) || (Event.m_Key >= KEY_F13 && Event.m_Key <= KEY_F24)) &&
|
||||
(Event.m_Key != KEY_F5 || !m_pClient->m_Menus.IsActive()))
|
||||
{
|
||||
int Mask = CBinds::GetModifierMask(Input());
|
||||
|
||||
// Look for a composed bind
|
||||
bool ret = false;
|
||||
if(m_pBinds->m_aapKeyBindings[Mask][Event.m_Key])
|
||||
{
|
||||
m_pBinds->GetConsole()->ExecuteLineStroked(Event.m_Flags & IInput::FLAG_PRESS, m_pBinds->m_aapKeyBindings[Mask][Event.m_Key]);
|
||||
ret = true;
|
||||
}
|
||||
// Look for a non composed bind
|
||||
if(!ret && m_pBinds->m_aapKeyBindings[0][Event.m_Key])
|
||||
{
|
||||
m_pBinds->GetConsole()->ExecuteLineStroked(Event.m_Flags & IInput::FLAG_PRESS, m_pBinds->m_aapKeyBindings[0][Event.m_Key]);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return m_pBinds->OnInput(Event);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -44,25 +33,19 @@ CBinds::CBinds()
|
|||
|
||||
CBinds::~CBinds()
|
||||
{
|
||||
for(int i = 0; i < KEY_LAST; i++)
|
||||
for(auto &apKeyBinding : m_aapKeyBindings)
|
||||
free(apKeyBinding[i]);
|
||||
UnbindAll();
|
||||
}
|
||||
|
||||
void CBinds::Bind(int KeyId, const char *pStr, bool FreeOnly, int ModifierCombination)
|
||||
{
|
||||
if(KeyId < 0 || KeyId >= KEY_LAST)
|
||||
return;
|
||||
dbg_assert(KeyId >= KEY_FIRST && KeyId < KEY_LAST, "KeyId invalid");
|
||||
dbg_assert(ModifierCombination >= MODIFIER_NONE && ModifierCombination < MODIFIER_COMBINATION_COUNT, "ModifierCombination invalid");
|
||||
|
||||
if(FreeOnly && Get(KeyId, ModifierCombination)[0])
|
||||
return;
|
||||
|
||||
free(m_aapKeyBindings[ModifierCombination][KeyId]);
|
||||
m_aapKeyBindings[ModifierCombination][KeyId] = 0;
|
||||
|
||||
// skip modifiers for +xxx binds
|
||||
if(pStr[0] == '+')
|
||||
ModifierCombination = 0;
|
||||
m_aapKeyBindings[ModifierCombination][KeyId] = nullptr;
|
||||
|
||||
char aBuf[256];
|
||||
if(!pStr[0])
|
||||
|
@ -120,59 +103,94 @@ int CBinds::GetModifierMaskOfKey(int Key)
|
|||
case KEY_RGUI:
|
||||
return 1 << CBinds::MODIFIER_GUI;
|
||||
default:
|
||||
return 0;
|
||||
return CBinds::MODIFIER_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
bool CBinds::OnInput(const IInput::CEvent &Event)
|
||||
{
|
||||
// don't handle invalid events
|
||||
if(Event.m_Key <= KEY_FIRST || Event.m_Key >= KEY_LAST)
|
||||
if((Event.m_Flags & (IInput::FLAG_PRESS | IInput::FLAG_RELEASE)) == 0)
|
||||
return false;
|
||||
|
||||
int Mask = GetModifierMask(Input());
|
||||
int KeyModifierMask = GetModifierMaskOfKey(Event.m_Key);
|
||||
Mask &= ~KeyModifierMask;
|
||||
const int KeyModifierMask = GetModifierMaskOfKey(Event.m_Key);
|
||||
const int ModifierMask = GetModifierMask(Input()) & ~KeyModifierMask;
|
||||
|
||||
bool ret = false;
|
||||
const char *pKey = nullptr;
|
||||
bool Handled = false;
|
||||
|
||||
if(m_aapKeyBindings[Mask][Event.m_Key])
|
||||
if(Event.m_Flags & IInput::FLAG_PRESS)
|
||||
{
|
||||
if(Event.m_Flags & IInput::FLAG_PRESS)
|
||||
auto ActiveBind = std::find_if(m_vActiveBinds.begin(), m_vActiveBinds.end(), [&](const CBindSlot &Bind) {
|
||||
return Event.m_Key == Bind.m_Key;
|
||||
});
|
||||
if(ActiveBind == m_vActiveBinds.end())
|
||||
{
|
||||
Console()->ExecuteLineStroked(1, m_aapKeyBindings[Mask][Event.m_Key]);
|
||||
pKey = m_aapKeyBindings[Mask][Event.m_Key];
|
||||
}
|
||||
// Have to check for nullptr again because the previous execute can unbind itself
|
||||
if(Event.m_Flags & IInput::FLAG_RELEASE && m_aapKeyBindings[Mask][Event.m_Key])
|
||||
Console()->ExecuteLineStroked(0, m_aapKeyBindings[Mask][Event.m_Key]);
|
||||
ret = true;
|
||||
}
|
||||
const auto &&OnPress = [&](int Mask) {
|
||||
const char *pBind = m_aapKeyBindings[Mask][Event.m_Key];
|
||||
if(g_Config.m_ClSubTickAiming)
|
||||
{
|
||||
if(str_comp("+fire", pBind) == 0 || str_comp("+hook", pBind) == 0)
|
||||
{
|
||||
m_MouseOnAction = true;
|
||||
}
|
||||
}
|
||||
Console()->ExecuteLineStroked(1, pBind);
|
||||
m_vActiveBinds.emplace_back(Event.m_Key, Mask);
|
||||
};
|
||||
|
||||
if(m_aapKeyBindings[0][Event.m_Key] && !ret)
|
||||
{
|
||||
// When ctrl+shift are pressed (ctrl+shift binds and also the hard-coded ctrl+shift+d, ctrl+shift+g, ctrl+shift+e), ignore other +xxx binds
|
||||
if(Event.m_Flags & IInput::FLAG_PRESS && Mask != ((1 << MODIFIER_CTRL) | (1 << MODIFIER_SHIFT)) && Mask != ((1 << MODIFIER_GUI) | (1 << MODIFIER_SHIFT)))
|
||||
{
|
||||
Console()->ExecuteLineStroked(1, m_aapKeyBindings[0][Event.m_Key]);
|
||||
pKey = m_aapKeyBindings[Mask][Event.m_Key];
|
||||
}
|
||||
// Have to check for nullptr again because the previous execute can unbind itself
|
||||
if(Event.m_Flags & IInput::FLAG_RELEASE && m_aapKeyBindings[0][Event.m_Key])
|
||||
Console()->ExecuteLineStroked(0, m_aapKeyBindings[0][Event.m_Key]);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if(g_Config.m_ClSubTickAiming && pKey)
|
||||
{
|
||||
if(str_comp("+fire", pKey) == 0 || str_comp("+hook", pKey) == 0)
|
||||
{
|
||||
m_MouseOnAction = true;
|
||||
if(m_aapKeyBindings[ModifierMask][Event.m_Key])
|
||||
{
|
||||
OnPress(ModifierMask);
|
||||
Handled = true;
|
||||
}
|
||||
else if(m_aapKeyBindings[MODIFIER_NONE][Event.m_Key] &&
|
||||
ModifierMask != ((1 << MODIFIER_CTRL) | (1 << MODIFIER_SHIFT)) &&
|
||||
ModifierMask != ((1 << MODIFIER_GUI) | (1 << MODIFIER_SHIFT)))
|
||||
{
|
||||
OnPress(MODIFIER_NONE);
|
||||
Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
if(Event.m_Flags & IInput::FLAG_RELEASE)
|
||||
{
|
||||
// Release active bind that uses this primary key
|
||||
auto ActiveBind = std::find_if(m_vActiveBinds.begin(), m_vActiveBinds.end(), [&](const CBindSlot &Bind) {
|
||||
return Event.m_Key == Bind.m_Key;
|
||||
});
|
||||
if(ActiveBind != m_vActiveBinds.end())
|
||||
{
|
||||
// Have to check for nullptr again because the previous execute can unbind itself
|
||||
if(m_aapKeyBindings[ActiveBind->m_ModifierMask][ActiveBind->m_Key])
|
||||
{
|
||||
Console()->ExecuteLineStroked(0, m_aapKeyBindings[ActiveBind->m_ModifierMask][ActiveBind->m_Key]);
|
||||
}
|
||||
m_vActiveBinds.erase(ActiveBind);
|
||||
Handled = true;
|
||||
}
|
||||
|
||||
// Release all active binds that use this modifier key
|
||||
if(KeyModifierMask != MODIFIER_NONE)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
auto ActiveModifierBind = std::find_if(m_vActiveBinds.begin(), m_vActiveBinds.end(), [&](const CBindSlot &Bind) {
|
||||
return (Bind.m_ModifierMask & KeyModifierMask) != 0;
|
||||
});
|
||||
if(ActiveModifierBind == m_vActiveBinds.end())
|
||||
break;
|
||||
// Have to check for nullptr again because the previous execute can unbind itself
|
||||
if(m_aapKeyBindings[ActiveModifierBind->m_ModifierMask][ActiveModifierBind->m_Key])
|
||||
{
|
||||
Console()->ExecuteLineStroked(0, m_aapKeyBindings[ActiveModifierBind->m_ModifierMask][ActiveModifierBind->m_Key]);
|
||||
}
|
||||
m_vActiveBinds.erase(ActiveModifierBind);
|
||||
Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Handled;
|
||||
}
|
||||
|
||||
void CBinds::UnbindAll()
|
||||
|
@ -182,35 +200,32 @@ void CBinds::UnbindAll()
|
|||
for(auto &pKeyBinding : apKeyBinding)
|
||||
{
|
||||
free(pKeyBinding);
|
||||
pKeyBinding = 0;
|
||||
pKeyBinding = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *CBinds::Get(int KeyId, int ModifierCombination)
|
||||
{
|
||||
if(KeyId > 0 && KeyId < KEY_LAST && m_aapKeyBindings[ModifierCombination][KeyId])
|
||||
return m_aapKeyBindings[ModifierCombination][KeyId];
|
||||
return "";
|
||||
dbg_assert(KeyId >= KEY_FIRST && KeyId < KEY_LAST, "KeyId invalid");
|
||||
dbg_assert(ModifierCombination >= MODIFIER_NONE && ModifierCombination < MODIFIER_COMBINATION_COUNT, "ModifierCombination invalid");
|
||||
return m_aapKeyBindings[ModifierCombination][KeyId] ? m_aapKeyBindings[ModifierCombination][KeyId] : "";
|
||||
}
|
||||
|
||||
void CBinds::GetKey(const char *pBindStr, char *pBuf, size_t BufSize)
|
||||
{
|
||||
pBuf[0] = 0;
|
||||
for(int Mod = 0; Mod < MODIFIER_COMBINATION_COUNT; Mod++)
|
||||
pBuf[0] = '\0';
|
||||
for(int Modifier = MODIFIER_NONE; Modifier < MODIFIER_COMBINATION_COUNT; Modifier++)
|
||||
{
|
||||
for(int KeyId = 0; KeyId < KEY_LAST; KeyId++)
|
||||
for(int KeyId = KEY_FIRST; KeyId < KEY_LAST; KeyId++)
|
||||
{
|
||||
const char *pBind = Get(KeyId, Mod);
|
||||
const char *pBind = Get(KeyId, Modifier);
|
||||
if(!pBind[0])
|
||||
continue;
|
||||
|
||||
if(str_comp(pBind, pBindStr) == 0)
|
||||
{
|
||||
if(Mod)
|
||||
str_format(pBuf, BufSize, "%s+%s", GetModifierName(Mod), Input()->KeyName(KeyId));
|
||||
else
|
||||
str_copy(pBuf, Input()->KeyName(KeyId), BufSize);
|
||||
str_format(pBuf, BufSize, "%s%s", GetKeyBindModifiersName(Modifier), Input()->KeyName(KeyId));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -219,8 +234,8 @@ void CBinds::GetKey(const char *pBindStr, char *pBuf, size_t BufSize)
|
|||
|
||||
void CBinds::SetDefaults()
|
||||
{
|
||||
// set default key bindings
|
||||
UnbindAll();
|
||||
|
||||
Bind(KEY_F1, "toggle_local_console");
|
||||
Bind(KEY_F2, "toggle_remote_console");
|
||||
Bind(KEY_TAB, "+scoreboard");
|
||||
|
@ -260,7 +275,6 @@ void CBinds::SetDefaults()
|
|||
Bind(KEY_Q, "say /pause");
|
||||
Bind(KEY_P, "say /pause");
|
||||
|
||||
// DDRace
|
||||
g_Config.m_ClDDRaceBindsSet = 0;
|
||||
SetDDRaceBinds(false);
|
||||
}
|
||||
|
@ -274,7 +288,6 @@ void CBinds::OnConsoleInit()
|
|||
Console()->Register("unbind", "s[key]", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key");
|
||||
Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys");
|
||||
|
||||
// default bindings
|
||||
SetDefaults();
|
||||
}
|
||||
|
||||
|
@ -282,10 +295,9 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData)
|
|||
{
|
||||
CBinds *pBinds = (CBinds *)pUserData;
|
||||
const char *pBindStr = pResult->GetString(0);
|
||||
int Modifier;
|
||||
int KeyId = pBinds->GetBindSlot(pBindStr, &Modifier);
|
||||
const CBindSlot BindSlot = pBinds->GetBindSlot(pBindStr);
|
||||
|
||||
if(!KeyId)
|
||||
if(!BindSlot.m_Key)
|
||||
{
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "key %s not found", pBindStr);
|
||||
|
@ -298,16 +310,16 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData)
|
|||
char aBuf[256];
|
||||
const char *pKeyName = pResult->GetString(0);
|
||||
|
||||
if(!pBinds->m_aapKeyBindings[Modifier][KeyId])
|
||||
str_format(aBuf, sizeof(aBuf), "%s (%d) is not bound", pKeyName, KeyId);
|
||||
if(!pBinds->m_aapKeyBindings[BindSlot.m_ModifierMask][BindSlot.m_Key])
|
||||
str_format(aBuf, sizeof(aBuf), "%s (%d) is not bound", pKeyName, BindSlot.m_Key);
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pKeyName, KeyId, pBinds->m_aapKeyBindings[Modifier][KeyId]);
|
||||
str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pKeyName, BindSlot.m_Key, pBinds->m_aapKeyBindings[BindSlot.m_ModifierMask][BindSlot.m_Key]);
|
||||
|
||||
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
|
||||
return;
|
||||
}
|
||||
|
||||
pBinds->Bind(KeyId, pResult->GetString(1), false, Modifier);
|
||||
pBinds->Bind(BindSlot.m_Key, pResult->GetString(1), false, BindSlot.m_ModifierMask);
|
||||
}
|
||||
|
||||
void CBinds::ConBinds(IConsole::IResult *pResult, void *pUserData)
|
||||
|
@ -317,35 +329,33 @@ void CBinds::ConBinds(IConsole::IResult *pResult, void *pUserData)
|
|||
{
|
||||
char aBuf[256];
|
||||
const char *pKeyName = pResult->GetString(0);
|
||||
|
||||
int Modifier;
|
||||
int KeyId = pBinds->GetBindSlot(pKeyName, &Modifier);
|
||||
if(!KeyId)
|
||||
const CBindSlot BindSlot = pBinds->GetBindSlot(pKeyName);
|
||||
if(!BindSlot.m_Key)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "key '%s' not found", pKeyName);
|
||||
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!pBinds->m_aapKeyBindings[Modifier][KeyId])
|
||||
str_format(aBuf, sizeof(aBuf), "%s (%d) is not bound", pKeyName, KeyId);
|
||||
if(!pBinds->m_aapKeyBindings[BindSlot.m_ModifierMask][BindSlot.m_Key])
|
||||
str_format(aBuf, sizeof(aBuf), "%s (%d) is not bound", pKeyName, BindSlot.m_Key);
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pKeyName, KeyId, pBinds->m_aapKeyBindings[Modifier][KeyId]);
|
||||
str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pKeyName, BindSlot.m_Key, pBinds->m_aapKeyBindings[BindSlot.m_ModifierMask][BindSlot.m_Key]);
|
||||
|
||||
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
|
||||
}
|
||||
}
|
||||
else if(pResult->NumArguments() == 0)
|
||||
else
|
||||
{
|
||||
char aBuf[1024];
|
||||
for(int i = 0; i < MODIFIER_COMBINATION_COUNT; i++)
|
||||
for(int Modifier = MODIFIER_NONE; Modifier < MODIFIER_COMBINATION_COUNT; Modifier++)
|
||||
{
|
||||
for(int j = 0; j < KEY_LAST; j++)
|
||||
for(int Key = KEY_FIRST; Key < KEY_LAST; Key++)
|
||||
{
|
||||
if(!pBinds->m_aapKeyBindings[i][j])
|
||||
if(!pBinds->m_aapKeyBindings[Modifier][Key])
|
||||
continue;
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "%s%s (%d) = %s", GetKeyBindModifiersName(i), pBinds->Input()->KeyName(j), j, pBinds->m_aapKeyBindings[i][j]);
|
||||
str_format(aBuf, sizeof(aBuf), "%s%s (%d) = %s", GetKeyBindModifiersName(Modifier), pBinds->Input()->KeyName(Key), Key, pBinds->m_aapKeyBindings[Modifier][Key]);
|
||||
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
|
||||
}
|
||||
}
|
||||
|
@ -356,10 +366,9 @@ void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData)
|
|||
{
|
||||
CBinds *pBinds = (CBinds *)pUserData;
|
||||
const char *pKeyName = pResult->GetString(0);
|
||||
int Modifier;
|
||||
int KeyId = pBinds->GetBindSlot(pKeyName, &Modifier);
|
||||
const CBindSlot BindSlot = pBinds->GetBindSlot(pKeyName);
|
||||
|
||||
if(!KeyId)
|
||||
if(!BindSlot.m_Key)
|
||||
{
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "key %s not found", pKeyName);
|
||||
|
@ -367,7 +376,7 @@ void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData)
|
|||
return;
|
||||
}
|
||||
|
||||
pBinds->Bind(KeyId, "", false, Modifier);
|
||||
pBinds->Bind(BindSlot.m_Key, "", false, BindSlot.m_ModifierMask);
|
||||
}
|
||||
|
||||
void CBinds::ConUnbindAll(IConsole::IResult *pResult, void *pUserData)
|
||||
|
@ -376,51 +385,31 @@ void CBinds::ConUnbindAll(IConsole::IResult *pResult, void *pUserData)
|
|||
pBinds->UnbindAll();
|
||||
}
|
||||
|
||||
int CBinds::GetKeyId(const char *pKeyName)
|
||||
CBinds::CBindSlot CBinds::GetBindSlot(const char *pBindString) const
|
||||
{
|
||||
// check for numeric
|
||||
if(pKeyName[0] == '&')
|
||||
{
|
||||
int i = str_toint(pKeyName + 1);
|
||||
if(i > 0 && i < KEY_LAST)
|
||||
return i; // numeric
|
||||
}
|
||||
|
||||
// search for key
|
||||
for(int i = 0; i < KEY_LAST; i++)
|
||||
{
|
||||
if(str_comp_nocase(pKeyName, Input()->KeyName(i)) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CBinds::GetBindSlot(const char *pBindString, int *pModifierCombination)
|
||||
{
|
||||
*pModifierCombination = MODIFIER_NONE;
|
||||
int ModifierMask = MODIFIER_NONE;
|
||||
char aMod[32];
|
||||
aMod[0] = '\0';
|
||||
const char *pKey = str_next_token(pBindString, "+", aMod, sizeof(aMod));
|
||||
while(aMod[0] && *(pKey))
|
||||
{
|
||||
if(!str_comp_nocase(aMod, "shift"))
|
||||
*pModifierCombination |= (1 << MODIFIER_SHIFT);
|
||||
ModifierMask |= (1 << MODIFIER_SHIFT);
|
||||
else if(!str_comp_nocase(aMod, "ctrl"))
|
||||
*pModifierCombination |= (1 << MODIFIER_CTRL);
|
||||
ModifierMask |= (1 << MODIFIER_CTRL);
|
||||
else if(!str_comp_nocase(aMod, "alt"))
|
||||
*pModifierCombination |= (1 << MODIFIER_ALT);
|
||||
ModifierMask |= (1 << MODIFIER_ALT);
|
||||
else if(!str_comp_nocase(aMod, "gui"))
|
||||
*pModifierCombination |= (1 << MODIFIER_GUI);
|
||||
ModifierMask |= (1 << MODIFIER_GUI);
|
||||
else
|
||||
return 0;
|
||||
return {KEY_UNKNOWN, MODIFIER_NONE};
|
||||
|
||||
if(str_find(pKey + 1, "+"))
|
||||
pKey = str_next_token(pKey + 1, "+", aMod, sizeof(aMod));
|
||||
else
|
||||
break;
|
||||
}
|
||||
return GetKeyId(*pModifierCombination == MODIFIER_NONE ? aMod : pKey + 1);
|
||||
return {Input()->FindKeyByName(ModifierMask == MODIFIER_NONE ? aMod : pKey + 1), ModifierMask};
|
||||
}
|
||||
|
||||
const char *CBinds::GetModifierName(int Modifier)
|
||||
|
@ -461,22 +450,22 @@ void CBinds::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData)
|
|||
CBinds *pSelf = (CBinds *)pUserData;
|
||||
|
||||
pConfigManager->WriteLine("unbindall");
|
||||
for(int i = 0; i < MODIFIER_COMBINATION_COUNT; i++)
|
||||
for(int Modifier = MODIFIER_NONE; Modifier < MODIFIER_COMBINATION_COUNT; Modifier++)
|
||||
{
|
||||
for(int j = 0; j < KEY_LAST; j++)
|
||||
for(int Key = KEY_FIRST; Key < KEY_LAST; Key++)
|
||||
{
|
||||
if(!pSelf->m_aapKeyBindings[i][j])
|
||||
if(!pSelf->m_aapKeyBindings[Modifier][Key])
|
||||
continue;
|
||||
|
||||
// worst case the str_escape can double the string length
|
||||
int Size = str_length(pSelf->m_aapKeyBindings[i][j]) * 2 + 30;
|
||||
int Size = str_length(pSelf->m_aapKeyBindings[Modifier][Key]) * 2 + 30;
|
||||
char *pBuffer = (char *)malloc(Size);
|
||||
char *pEnd = pBuffer + Size;
|
||||
|
||||
str_format(pBuffer, Size, "bind %s%s \"", GetKeyBindModifiersName(i), pSelf->Input()->KeyName(j));
|
||||
str_format(pBuffer, Size, "bind %s%s \"", GetKeyBindModifiersName(Modifier), pSelf->Input()->KeyName(Key));
|
||||
// process the string. we need to escape some characters
|
||||
char *pDst = pBuffer + str_length(pBuffer);
|
||||
str_escape(&pDst, pSelf->m_aapKeyBindings[i][j], pEnd);
|
||||
str_escape(&pDst, pSelf->m_aapKeyBindings[Modifier][Key], pEnd);
|
||||
str_append(pBuffer, "\"", Size);
|
||||
|
||||
pConfigManager->WriteLine(pBuffer);
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
|
||||
#include <game/client/component.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class IConfigManager;
|
||||
|
||||
class CBinds : public CComponent
|
||||
{
|
||||
int GetKeyId(const char *pKeyName);
|
||||
|
||||
static void ConBind(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConBinds(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConUnbind(IConsole::IResult *pResult, void *pUserData);
|
||||
|
@ -22,6 +22,20 @@ class CBinds : public CComponent
|
|||
|
||||
static void ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData);
|
||||
|
||||
class CBindSlot
|
||||
{
|
||||
public:
|
||||
int m_Key;
|
||||
int m_ModifierMask;
|
||||
|
||||
CBindSlot(int Key, int ModifierMask) :
|
||||
m_Key(Key),
|
||||
m_ModifierMask(ModifierMask)
|
||||
{
|
||||
}
|
||||
};
|
||||
CBindSlot GetBindSlot(const char *pBindString) const;
|
||||
|
||||
public:
|
||||
CBinds();
|
||||
~CBinds();
|
||||
|
@ -55,7 +69,6 @@ public:
|
|||
void UnbindAll();
|
||||
const char *Get(int KeyId, int ModifierCombination);
|
||||
void GetKey(const char *pBindStr, char *pBuf, size_t BufSize);
|
||||
int GetBindSlot(const char *pBindString, int *pModifierCombination);
|
||||
static int GetModifierMask(IInput *pInput);
|
||||
static int GetModifierMaskOfKey(int Key);
|
||||
static const char *GetModifierName(int Modifier);
|
||||
|
@ -70,5 +83,6 @@ public:
|
|||
|
||||
private:
|
||||
char *m_aapKeyBindings[MODIFIER_COMBINATION_COUNT][KEY_LAST];
|
||||
std::vector<CBindSlot> m_vActiveBinds;
|
||||
};
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue