Implemented support for Shift, Ctrl, Alt modifiers for binds (console-only for now)

This commit is contained in:
Jordy Ruiz 2018-10-30 17:41:26 +01:00
parent 9eeb7dffa5
commit cfaa0ea638
4 changed files with 176 additions and 79 deletions

View file

@ -25,82 +25,119 @@ const char CBinds::s_aaDefaultBindValues[][32] = {
"ready_change", "ready_change",
}; };
bool CBinds::CBindsSpecial::OnInput(IInput::CEvent Event)
{
// don't handle invalid events and keys that arn't set to anything
if(((Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F12) || (Event.m_Key >= KEY_F13 && Event.m_Key <= KEY_F24)) && m_pBinds->m_aaKeyBindings[Event.m_Key][0] != 0)
{
int Stroke = 0;
if(Event.m_Flags&IInput::FLAG_PRESS)
Stroke = 1;
m_pBinds->GetConsole()->ExecuteLineStroked(Stroke, m_pBinds->m_aaKeyBindings[Event.m_Key]);
return true;
}
return false;
}
CBinds::CBinds() CBinds::CBinds()
{ {
mem_zero(m_aaKeyBindings, sizeof(m_aaKeyBindings)); mem_zero(m_aaaKeyBindings, sizeof(m_aaaKeyBindings));
m_SpecialBinds.m_pBinds = this; m_SpecialBinds.m_pBinds = this;
} }
void CBinds::Bind(int KeyID, const char *pStr) void CBinds::Bind(int KeyID, int Modifier, const char *pStr)
{ {
if(KeyID < 0 || KeyID >= KEY_LAST) if(KeyID < 0 || KeyID >= KEY_LAST)
return; return;
str_copy(m_aaKeyBindings[KeyID], pStr, sizeof(m_aaKeyBindings[KeyID])); str_copy(m_aaaKeyBindings[KeyID][Modifier], pStr, sizeof(m_aaaKeyBindings[KeyID][Modifier]));
char aBuf[256]; char aBuf[256];
if(!m_aaKeyBindings[KeyID][0]) if(!m_aaaKeyBindings[KeyID][Modifier][0])
str_format(aBuf, sizeof(aBuf), "unbound %s (%d)", Input()->KeyName(KeyID), KeyID); str_format(aBuf, sizeof(aBuf), "unbound %s%s (%d)", GetModifierName(Modifier),Input()->KeyName(KeyID), KeyID);
else else
str_format(aBuf, sizeof(aBuf), "bound %s (%d) = %s", Input()->KeyName(KeyID), KeyID, m_aaKeyBindings[KeyID]); str_format(aBuf, sizeof(aBuf), "bound %s%s (%d) = %s", GetModifierName(Modifier),Input()->KeyName(KeyID), KeyID, m_aaaKeyBindings[KeyID][Modifier]);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf);
} }
bool CBinds::CBindsSpecial::OnInput(IInput::CEvent Event)
{
int Mask = 0;
// since we only handle one modifier, when doing ctrl+q and shift+q, execute both
Mask |= Input()->KeyIsPressed(KEY_LSHIFT) << MODIFIER_SHIFT;
Mask |= Input()->KeyIsPressed(KEY_RSHIFT) << MODIFIER_SHIFT;
Mask |= Input()->KeyIsPressed(KEY_LCTRL) << MODIFIER_CTRL;
Mask |= Input()->KeyIsPressed(KEY_RCTRL) << MODIFIER_CTRL;
Mask |= Input()->KeyIsPressed(KEY_LALT) << MODIFIER_ALT;
if(Mask == 0)
Mask = 1; // if no modifier, flag with MODIFIER_NONE
bool rtn = false;
// don't handle invalid events and keys that aren't set to anything
if(!((Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F12) || (Event.m_Key >= KEY_F13 && Event.m_Key <= KEY_F24)))
return false;
for(int m = 0; m < MODIFIER_COUNT; m++)
{
if((Mask&(1 << m)) && m_pBinds->m_aaaKeyBindings[Event.m_Key][m][0] != 0)
{
int Stroke = 0;
if(Event.m_Flags&IInput::FLAG_PRESS)
Stroke = 1;
m_pBinds->GetConsole()->ExecuteLineStroked(Stroke, m_pBinds->m_aaaKeyBindings[Event.m_Key][m]);
rtn = true;
}
}
return rtn;
}
bool CBinds::OnInput(IInput::CEvent e) bool CBinds::OnInput(IInput::CEvent e)
{ {
// don't handle invalid events and keys that arn't set to anything int Mask = 0;
if(e.m_Key <= 0 || e.m_Key >= KEY_LAST || m_aaKeyBindings[e.m_Key][0] == 0) // since we only handle one modifier, when doing ctrl+q and shift+q, execute both
Mask |= Input()->KeyIsPressed(KEY_LSHIFT) << MODIFIER_SHIFT;
Mask |= Input()->KeyIsPressed(KEY_RSHIFT) << MODIFIER_SHIFT;
Mask |= Input()->KeyIsPressed(KEY_LCTRL) << MODIFIER_CTRL;
Mask |= Input()->KeyIsPressed(KEY_RCTRL) << MODIFIER_CTRL;
Mask |= Input()->KeyIsPressed(KEY_LALT) << MODIFIER_ALT;
if(Mask == 0)
Mask = 1; // if no modifier, flag with MODIFIER_NONE
// don't handle invalid events and keys that aren't set to anything
if(e.m_Key <= 0 || e.m_Key >= KEY_LAST)
return false; return false;
if(e.m_Flags&IInput::FLAG_PRESS) bool rtn = false;
Console()->ExecuteLineStroked(1, m_aaKeyBindings[e.m_Key]); for(int m = 0; m < MODIFIER_COUNT; m++)
if(e.m_Flags&IInput::FLAG_RELEASE) {
Console()->ExecuteLineStroked(0, m_aaKeyBindings[e.m_Key]); if((Mask&(1 << m)) && m_aaaKeyBindings[e.m_Key][m][0] == 0)
return true; continue;
if(e.m_Flags&IInput::FLAG_PRESS)
Console()->ExecuteLineStroked(1, m_aaaKeyBindings[e.m_Key][m]);
if(e.m_Flags&IInput::FLAG_RELEASE)
Console()->ExecuteLineStroked(0, m_aaaKeyBindings[e.m_Key][m]);
rtn = true;
}
return rtn;
} }
void CBinds::UnbindAll() void CBinds::UnbindAll()
{ {
for(int i = 0; i < KEY_LAST; i++) for(int i = 0; i < KEY_LAST; i++)
m_aaKeyBindings[i][0] = 0; for(int m = 0; m < MODIFIER_COUNT; m++)
m_aaaKeyBindings[i][m][0] = 0;
} }
const char *CBinds::Get(int KeyID) const char *CBinds::Get(int KeyID, int Modifier)
{ {
if(KeyID > 0 && KeyID < KEY_LAST) if(KeyID > 0 && KeyID < KEY_LAST)
return m_aaKeyBindings[KeyID]; return m_aaaKeyBindings[KeyID][Modifier];
return ""; return "";
} }
const char *CBinds::GetKey(const char *pBindStr) void CBinds::GetKey(const char *pBindStr, char aBuf[64])
{ {
for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) aBuf[0] = 0;
for(int KeyID = 0; KeyID < KEY_LAST; KeyID++)
{ {
const char *pBind = Get(KeyId); for(int m = 0; m < MODIFIER_COUNT; m++)
if(!pBind[0]) {
continue; const char *pBind = Get(KeyID, m);
if(!pBind[0])
continue;
if(str_comp(pBind, pBindStr) == 0) if(str_comp(pBind, pBindStr) == 0)
return Input()->KeyName(KeyId); str_format(aBuf, 64, "key %s%s not found", Input()->KeyName(KeyID), GetModifierName(m));
}
} }
return "";
} }
void CBinds::SetDefaults() void CBinds::SetDefaults()
@ -110,7 +147,7 @@ void CBinds::SetDefaults()
const int count = sizeof(s_aDefaultBindKeys)/sizeof(int); const int count = sizeof(s_aDefaultBindKeys)/sizeof(int);
dbg_assert(count == sizeof(s_aaDefaultBindValues)/32, "the count of bind keys differs from that of bind values!"); dbg_assert(count == sizeof(s_aaDefaultBindValues)/32, "the count of bind keys differs from that of bind values!");
for(int i = 0; i < count; i++) for(int i = 0; i < count; i++)
Bind(s_aDefaultBindKeys[i], s_aaDefaultBindValues[i]); Bind(s_aDefaultBindKeys[i], MODIFIER_NONE, s_aaDefaultBindValues[i]);
} }
void CBinds::OnConsoleInit() void CBinds::OnConsoleInit()
@ -133,7 +170,8 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData)
{ {
CBinds *pBinds = (CBinds *)pUserData; CBinds *pBinds = (CBinds *)pUserData;
const char *pKeyName = pResult->GetString(0); const char *pKeyName = pResult->GetString(0);
int id = pBinds->GetKeyID(pKeyName); int modifier;
int id = pBinds->DecodeBindString(pKeyName, &modifier);
if(!id) if(!id)
{ {
@ -143,7 +181,7 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData)
return; return;
} }
pBinds->Bind(id, pResult->GetString(1)); pBinds->Bind(id, modifier, pResult->GetString(1));
} }
@ -151,7 +189,8 @@ void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData)
{ {
CBinds *pBinds = (CBinds *)pUserData; CBinds *pBinds = (CBinds *)pUserData;
const char *pKeyName = pResult->GetString(0); const char *pKeyName = pResult->GetString(0);
int id = pBinds->GetKeyID(pKeyName); int modifier;
int id = pBinds->DecodeBindString(pKeyName, &modifier);
if(!id) if(!id)
{ {
@ -161,7 +200,7 @@ void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData)
return; return;
} }
pBinds->Bind(id, ""); pBinds->Bind(id, modifier, "");
} }
@ -178,15 +217,40 @@ void CBinds::ConDumpBinds(IConsole::IResult *pResult, void *pUserData)
char aBuf[1024]; char aBuf[1024];
for(int i = 0; i < KEY_LAST; i++) for(int i = 0; i < KEY_LAST; i++)
{ {
if(pBinds->m_aaKeyBindings[i][0] == 0) for(int m = 0; m < MODIFIER_COUNT; m++)
continue; {
str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pBinds->Input()->KeyName(i), i, pBinds->m_aaKeyBindings[i]); if(pBinds->m_aaaKeyBindings[i][m][0] == 0)
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); continue;
str_format(aBuf, sizeof(aBuf), "%s%s (%d) = %s", GetModifierName(m), pBinds->Input()->KeyName(i), i, pBinds->m_aaaKeyBindings[i][m]);
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf);
}
} }
} }
int CBinds::GetKeyID(const char *pKeyName) int CBinds::DecodeBindString(const char *pKeyName, int* pModifier)
{ {
// check for modifier of type xxx+xxx
char aBuf[64];
str_copy(aBuf, pKeyName, sizeof(aBuf));
const char* pStr = str_find(aBuf, "+");
*pModifier = 0;
if(pStr && *(pStr+1)) // make sure the '+' isn't the last character
{
aBuf[pStr-aBuf] = 0; // *pStr=0 (split the string where the + is)
char* pModifierStr = aBuf;
if(str_comp(pModifierStr, "shift") == 0)
*pModifier = MODIFIER_SHIFT;
else if(str_comp(pModifierStr, "ctrl") == 0)
*pModifier = MODIFIER_CTRL;
else if(str_comp(pModifierStr, "alt") == 0)
*pModifier = MODIFIER_ALT;
else
return 0;
pKeyName = pStr + 1;
if(!pKeyName)
return 0;
}
// check for numeric // check for numeric
if(pKeyName[0] == '&') if(pKeyName[0] == '&')
{ {
@ -205,6 +269,24 @@ int CBinds::GetKeyID(const char *pKeyName)
return 0; return 0;
} }
const char *CBinds::GetModifierName(int m)
{
switch(m)
{
case 0:
return "";
case MODIFIER_SHIFT:
return "shift+";
case MODIFIER_CTRL:
return "ctrl+";
case MODIFIER_ALT:
return "alt+";
default:
return "";
}
}
void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData)
{ {
CBinds *pSelf = (CBinds *)pUserData; CBinds *pSelf = (CBinds *)pUserData;
@ -213,31 +295,35 @@ void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData)
char *pEnd = aBuffer+sizeof(aBuffer)-8; char *pEnd = aBuffer+sizeof(aBuffer)-8;
for(int i = 0; i < KEY_LAST; i++) for(int i = 0; i < KEY_LAST; i++)
{ {
if(pSelf->m_aaKeyBindings[i][0] == 0) for(int m = 0; m < MODIFIER_COUNT; m++)
continue;
str_format(aBuffer, sizeof(aBuffer), "bind %s ", pSelf->Input()->KeyName(i));
// process the string. we need to escape some characters
const char *pSrc = pSelf->m_aaKeyBindings[i];
char *pDst = aBuffer + str_length(aBuffer);
*pDst++ = '"';
while(*pSrc && pDst < pEnd)
{ {
if(*pSrc == '"' || *pSrc == '\\') // escape \ and " if(pSelf->m_aaaKeyBindings[i][m][0] == 0)
*pDst++ = '\\'; continue;
*pDst++ = *pSrc++;
}
*pDst++ = '"';
*pDst++ = 0;
pConfig->WriteLine(aBuffer); str_format(aBuffer, sizeof(aBuffer), "bind %s%s ", GetModifierName(m), pSelf->Input()->KeyName(i));
// process the string. we need to escape some characters
const char *pSrc = pSelf->m_aaaKeyBindings[i][m];
char *pDst = aBuffer + str_length(aBuffer);
*pDst++ = '"';
while(*pSrc && pDst < pEnd)
{
if(*pSrc == '"' || *pSrc == '\\') // escape \ and "
*pDst++ = '\\';
*pDst++ = *pSrc++;
}
*pDst++ = '"';
*pDst++ = 0;
pConfig->WriteLine(aBuffer);
}
} }
// default binds can only be non-composed right now, so only check for that
for(unsigned j = 0; j < sizeof(s_aDefaultBindKeys)/sizeof(int); j++) for(unsigned j = 0; j < sizeof(s_aDefaultBindKeys)/sizeof(int); j++)
{ {
const int i = s_aDefaultBindKeys[j]; const int i = s_aDefaultBindKeys[j];
if(pSelf->m_aaKeyBindings[i][0] == 0) if(pSelf->m_aaaKeyBindings[i][0][0] == 0)
{ {
// explicitly unbind keys that were unbound by the user // explicitly unbind keys that were unbound by the user
str_format(aBuffer, sizeof(aBuffer), "unbind %s ", pSelf->Input()->KeyName(i)); str_format(aBuffer, sizeof(aBuffer), "unbind %s ", pSelf->Input()->KeyName(i));

View file

@ -7,9 +7,8 @@
class CBinds : public CComponent class CBinds : public CComponent
{ {
char m_aaKeyBindings[KEY_LAST][128]; int DecodeBindString(const char *pKeyName, int* pModifier);
static const char *GetModifierName(int m);
int GetKeyID(const char *pKeyName);
static void ConBind(IConsole::IResult *pResult, void *pUserData); static void ConBind(IConsole::IResult *pResult, void *pUserData);
static void ConUnbind(IConsole::IResult *pResult, void *pUserData); static void ConUnbind(IConsole::IResult *pResult, void *pUserData);
@ -29,18 +28,28 @@ public:
virtual bool OnInput(IInput::CEvent Event); virtual bool OnInput(IInput::CEvent Event);
}; };
enum
{
MODIFIER_NONE=0,
MODIFIER_SHIFT,
MODIFIER_CTRL,
MODIFIER_ALT,
MODIFIER_COUNT
};
CBindsSpecial m_SpecialBinds; CBindsSpecial m_SpecialBinds;
void Bind(int KeyID, const char *pStr); void Bind(int KeyID, int Modifier, const char *pStr);
void SetDefaults(); void SetDefaults();
void UnbindAll(); void UnbindAll();
const char *Get(int KeyID); const char *Get(int KeyID, int Modifier);
const char *GetKey(const char *pBindStr); void GetKey(const char *pBindStr, char aBuf[64]);
virtual void OnConsoleInit(); virtual void OnConsoleInit();
virtual bool OnInput(IInput::CEvent Event); virtual bool OnInput(IInput::CEvent Event);
private: private:
char m_aaaKeyBindings[KEY_LAST][MODIFIER_COUNT][128];
static const int s_aDefaultBindKeys[]; static const int s_aDefaultBindKeys[];
static const char s_aaDefaultBindValues[][32]; static const char s_aaDefaultBindValues[][32];
}; };

View file

@ -436,13 +436,14 @@ void CHud::RenderVoting()
CUIRect Base = {5, 88, 100, 4}; CUIRect Base = {5, 88, 100, 4};
m_pClient->m_pVoting->RenderBars(Base, false); m_pClient->m_pVoting->RenderBars(Base, false);
const char *pYesKey = m_pClient->m_pBinds->GetKey("vote yes"); char aBufYes[64], aBufNo[64];
const char *pNoKey = m_pClient->m_pBinds->GetKey("vote no"); m_pClient->m_pBinds->GetKey("vote yes", aBufYes);
str_format(aBuf, sizeof(aBuf), "%s - %s", pYesKey, Localize("Vote yes")); m_pClient->m_pBinds->GetKey("vote no", aBufNo);
str_format(aBuf, sizeof(aBuf), "%s - %s", aBufYes, Localize("Vote yes"));
Base.y += Base.h+1; Base.y += Base.h+1;
UI()->DoLabel(&Base, aBuf, 6.0f, CUI::ALIGN_LEFT); UI()->DoLabel(&Base, aBuf, 6.0f, CUI::ALIGN_LEFT);
str_format(aBuf, sizeof(aBuf), "%s - %s", Localize("Vote no"), pNoKey); str_format(aBuf, sizeof(aBuf), "%s - %s", Localize("Vote no"), aBufNo);
UI()->DoLabel(&Base, aBuf, 6.0f, CUI::ALIGN_RIGHT); UI()->DoLabel(&Base, aBuf, 6.0f, CUI::ALIGN_RIGHT);
} }

View file

@ -184,6 +184,7 @@ void CGameClient::OnConsoleInit()
m_All.Add(m_pEffects); // doesn't render anything, just updates effects m_All.Add(m_pEffects); // doesn't render anything, just updates effects
m_All.Add(m_pParticles); // doesn't render anything, just updates all the particles m_All.Add(m_pParticles); // doesn't render anything, just updates all the particles
m_All.Add(m_pBinds); m_All.Add(m_pBinds);
m_All.Add(&m_pBinds->m_SpecialBinds);
m_All.Add(m_pControls); m_All.Add(m_pControls);
m_All.Add(m_pCamera); m_All.Add(m_pCamera);
m_All.Add(m_pSounds); m_All.Add(m_pSounds);