Remove gamepad ids from key codes

We want one gamepad key mapping to work with multiple gamepads, so
including the id there doesn't make sense.

Additionally, the gamepad id may change during the game (controller
hot-plugging).
liquid_container
Lukas Werling 2016-02-20 22:25:07 +01:00
parent 9f69c650d6
commit 9e0143b998
6 changed files with 59 additions and 29 deletions

View File

@ -24,6 +24,7 @@
#include "C4PlayerList.h"
#include "C4Control.h"
#include "C4Game.h"
#include "C4GamePadCon.h"
#include "C4Log.h"
#include "C4GraphicsResource.h"
#include "C4MouseControl.h"
@ -1011,6 +1012,13 @@ void C4PlayerControl::CompileFunc(StdCompiler *pComp)
bool C4PlayerControl::ProcessKeyEvent(const C4KeyCodeEx &pressed_key, const C4KeyCodeEx &matched_key, ControlState state, const C4KeyEventData &rKeyExtraData, bool reset_down_states_only, bool *clear_recent_keys)
{
if (Key_IsGamepad(pressed_key.Key))
{
// We have to filter gamepad events here.
C4Player *plr = ::Players.Get(iPlr);
if (!plr || !plr->pGamepad || plr->pGamepad->GetID() != pressed_key.deviceId)
return false;
}
// collect all matching keys
C4PlayerControlAssignmentPVec Matches;
assert(pControlSet); // shouldn't get this callback for players without control set

View File

@ -1891,6 +1891,12 @@ bool C4Game::DoKeyboardInput(C4KeyCode vk_code, C4KeyEventType eEventType, bool
#endif
// compose key
C4KeyCodeEx Key(vk_code, C4KeyShiftState(fAlt*KEYS_Alt + fCtrl*KEYS_Control + fShift*KEYS_Shift), fRepeated);
return DoKeyboardInput(Key, eEventType, pForDialog, fPlrCtrlOnly, iStrength);
}
bool C4Game::DoKeyboardInput(C4KeyCodeEx Key, C4KeyEventType eEventType, class C4GUI::Dialog *pForDialog, bool fPlrCtrlOnly, int32_t iStrength)
{
Key.FixShiftKeys();
// compose keyboard scope
DWORD InScope = 0;

View File

@ -146,6 +146,7 @@ public:
void Evaluate();
void ShowGameOverDlg();
bool DoKeyboardInput(C4KeyCode vk_code, C4KeyEventType eEventType, bool fAlt, bool fCtrl, bool fShift, bool fRepeated, class C4GUI::Dialog *pForDialog=NULL, bool fPlrCtrlOnly=false, int32_t iStrength=-1);
bool DoKeyboardInput(C4KeyCodeEx Key, C4KeyEventType eEventType, class C4GUI::Dialog *pForDialog=NULL, bool fPlrCtrlOnly=false, int32_t iStrength=-1);
void DrawCrewOverheadText(C4TargetFacet &cgo, int32_t iPlayer);
void FixRandom(int32_t iSeed);
bool Init();

View File

@ -193,6 +193,11 @@ const C4KeyCodeMapEntry KeyCodeMap[] = {
};
#endif
C4KeyCodeEx::C4KeyCodeEx(C4KeyCode key, C4KeyShiftState Shift, bool fIsRepeated, int32_t deviceId)
: Key(key), dwShift(Shift), fRepeated(fIsRepeated), deviceId(deviceId)
{
}
void C4KeyCodeEx::FixShiftKeys()
{
// reduce stuff like Ctrl+RightCtrl to simply RightCtrl
@ -252,10 +257,9 @@ C4KeyCode C4KeyCodeEx::String2KeyCode(const StdStrBuf &sName)
std::cmatch matches;
if (std::regex_match(sName.getData(), matches, controller_re))
{
int iGamepad = 0; // TODO: Gamepad code selected later on.
auto keycode_it = controllercodes.find(matches[1].str());
if (keycode_it != controllercodes.end())
return KEY_Gamepad(iGamepad, keycode_it->second);
return KEY_Gamepad(keycode_it->second);
else
return KEY_Undefined;
@ -622,6 +626,15 @@ C4CustomKey::~C4CustomKey()
(*i)->Deref();
}
bool C4CustomKey::IsCodeMatched(const C4KeyCodeEx &key) const
{
const CodeList &codes = GetCodes();
for (const auto &code : codes)
if (code == key)
return true;
return false;
}
void C4CustomKey::Update(const C4CustomKey *pByKey)
{
assert(pByKey);
@ -832,9 +845,8 @@ bool C4KeyboardInput::DoInput(const C4KeyCodeEx &InKey, C4KeyEventType InEvent,
FallbackKeys[iKeyRangeCnt++] = InKey.Key;
if (Key_IsGamepadButton(InKey.Key))
{
uint8_t byGamepad = Key_GetGamepad(InKey.Key);
// "any gamepad button"-event
FallbackKeys[iKeyRangeCnt++] = KEY_Gamepad(byGamepad, KEY_CONTROLLER_AnyButton);
FallbackKeys[iKeyRangeCnt++] = KEY_Gamepad(KEY_CONTROLLER_AnyButton);
}
else if (Key_IsGamepadAxis(InKey.Key))
{

View File

@ -110,10 +110,10 @@ const C4KeyCode
inline uint8_t KEY_CONTROLLER_Button(uint8_t idx) { return KEY_CONTROLLER_ButtonMin+idx; }
inline uint8_t KEY_CONTROLLER_Axis(uint8_t idx, bool fMax) { return KEY_CONTROLLER_AxisMin+2*idx+fMax; }
inline C4KeyCode KEY_Gamepad(uint8_t idGamepad, uint8_t idButton) // convert gamepad key to Clonk-gamepad-keycode
inline C4KeyCode KEY_Gamepad(uint8_t idButton) // convert gamepad key to Clonk-gamepad-keycode
{
// mask key as 0x0042ggbb, where gg is gamepad ID and bb is button ID.
return KEY_CONTROLLER_Mask + (idGamepad<<8) + idButton;
// mask key as 0x004200bb, where 00 used to be the gamepad ID and bb is button ID.
return KEY_CONTROLLER_Mask + idButton;
}
inline bool Key_IsGamepad(C4KeyCode key)
@ -205,6 +205,8 @@ struct C4KeyCodeEx
C4KeyCode Key; // the key
DWORD dwShift; // the status of Alt, Shift, Control
int32_t deviceId;
// if set, the keycode was generated by a key that has been held down
// this flag is ignored in comparison operations
bool fRepeated;
@ -229,8 +231,7 @@ struct C4KeyCodeEx
void CompileFunc(StdCompiler *pComp, StdStrBuf *pOutBuf=NULL);
C4KeyCodeEx(C4KeyCode Key = KEY_Default, C4KeyShiftState Shift = KEYS_None, bool fIsRepeated = false)
: Key(Key), dwShift(Shift), fRepeated(fIsRepeated) {}
C4KeyCodeEx(C4KeyCode Key = KEY_Default, C4KeyShiftState Shift = KEYS_None, bool fIsRepeated = false, int32_t deviceId = -1);
bool IsRepeated() const { return fRepeated; }
@ -253,17 +254,17 @@ struct C4KeyEventData
// Helper functions for high-level GUI control mappings.
namespace ControllerKeys {
template<class T> void Any(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_AnyButton))); }
template<class T> void Cancel(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_ButtonB))); }
template<class T> void Ok(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_ButtonA))); }
template<class T> void Left(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_AxisLeftXLeft)));
keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_ButtonDpadLeft))); }
template<class T> void Right(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_AxisLeftXRight)));
keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_ButtonDpadRight))); }
template<class T> void Up(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_AxisLeftYUp)));
keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_ButtonDpadUp))); }
template<class T> void Down(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_AxisLeftYDown)));
keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_CONTROLLER_ButtonDpadDown))); }
template<class T> void Any(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_AnyButton))); }
template<class T> void Cancel(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_ButtonB))); }
template<class T> void Ok(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_ButtonA))); }
template<class T> void Left(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_AxisLeftXLeft)));
keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_ButtonDpadLeft))); }
template<class T> void Right(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_AxisLeftXRight)));
keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_ButtonDpadRight))); }
template<class T> void Up(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_AxisLeftYUp)));
keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_ButtonDpadUp))); }
template<class T> void Down(T &keys) { keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_AxisLeftYDown)));
keys.push_back(C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_ButtonDpadDown))); }
}
// callback interface
@ -460,7 +461,7 @@ public:
const StdStrBuf &GetName() const { return Name; }
C4KeyScope GetScope() const { return Scope; }
unsigned int GetPriority() const { return uiPriority; }
bool IsCodeMatched(const C4KeyCodeEx &key) const { const CodeList &codes = GetCodes(); return (std::find(codes.begin(),codes.end(),key) != codes.end()); }
bool IsCodeMatched(const C4KeyCodeEx &key) const;
void Update(const C4CustomKey *pByKey); // merge given key into this
bool Execute(C4KeyEventType eEv, C4KeyCodeEx key);

View File

@ -39,6 +39,8 @@ C4GamePadControl::C4GamePadControl()
C4GamePadControl::~C4GamePadControl()
{
// All gamepads have to be released before quitting SDL.
Gamepads.clear();
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS);
}
@ -71,8 +73,8 @@ void C4GamePadControl::FeedEvent(const SDL_Event& event, int feed)
{
case SDL_CONTROLLERAXISMOTION:
{
C4KeyCode minCode = KEY_Gamepad(event.caxis.which, KEY_CONTROLLER_Axis(event.caxis.axis, false));
C4KeyCode maxCode = KEY_Gamepad(event.caxis.which, KEY_CONTROLLER_Axis(event.caxis.axis, true));
C4KeyCode minCode = KEY_Gamepad(KEY_CONTROLLER_Axis(event.caxis.axis, false));
C4KeyCode maxCode = KEY_Gamepad(KEY_CONTROLLER_Axis(event.caxis.axis, true));
int32_t value = std::abs(event.caxis.value);
uint8_t which = event.caxis.which;
C4KeyCode keyCode = event.caxis.value >= 0 ? maxCode : minCode;
@ -80,8 +82,8 @@ void C4GamePadControl::FeedEvent(const SDL_Event& event, int feed)
auto doInput = [&](C4KeyEventType event, int32_t strength)
{
Game.DoKeyboardInput(
KEY_Gamepad(which, keyCode), event,
false, false, false, false, NULL, false, strength);
C4KeyCodeEx(KEY_Gamepad(keyCode), KEYS_None, false, which),
event, NULL, false, strength);
};
if (feed & FEED_BUTTONS)
@ -108,14 +110,14 @@ void C4GamePadControl::FeedEvent(const SDL_Event& event, int feed)
case SDL_CONTROLLERBUTTONDOWN:
if (feed & FEED_BUTTONS)
Game.DoKeyboardInput(
KEY_Gamepad(event.cbutton.which, KEY_CONTROLLER_Button(event.cbutton.button)),
KEYEV_Down, false, false, false, false);
C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_Button(event.cbutton.button)), KEYS_None, false, event.cbutton.which),
KEYEV_Down);
break;
case SDL_CONTROLLERBUTTONUP:
if (feed & FEED_BUTTONS)
Game.DoKeyboardInput(
KEY_Gamepad(event.cbutton.which, KEY_CONTROLLER_Button(event.cbutton.button)),
KEYEV_Up, false, false, false, false);
C4KeyCodeEx(KEY_Gamepad(KEY_CONTROLLER_Button(event.cbutton.button)), KEYS_None, false, event.cbutton.which),
KEYEV_Up);
break;
}
}