Allow using mouse keys and key combinations from the control assignment configuration dialogue (#1693, #1692)

install-platforms
Julius Michaelis 2018-01-15 00:28:05 +01:00
parent 417d10ed97
commit b115641685
2 changed files with 78 additions and 3 deletions

View File

@ -23,6 +23,7 @@
#include "graphics/C4Draw.h"
#include "graphics/C4GraphicsResource.h"
#include "gui/C4MouseControl.h"
#include "gui/C4KeyboardInput.h"
#include "gui/C4StartupMainDlg.h"
#include "network/C4Network2.h"
#include "platform/C4GamePadCon.h"
@ -147,7 +148,17 @@ C4StartupOptionsDlg::KeySelDialog::KeySelDialog(const C4PlayerControlAssignment
: C4GUI::MessageDialog(GetDlgMessage(assignment, assignment_set).getData(), LoadResStr("IDS_MSG_DEFINEKEY"), C4GUI::MessageDialog::btnAbort | C4GUI::MessageDialog::btnReset, GetDlgIcon(assignment_set), C4GUI::MessageDialog::dsRegular),
key(KEY_Undefined), assignment(assignment), assignment_set(assignment_set)
{
pKeyListener = new C4KeyBinding(C4KeyCodeEx(KEY_Any, KEYS_None), "DefineKey", KEYSCOPE_Gui, new C4GUI::DlgKeyCBPassKey<C4StartupOptionsDlg::KeySelDialog>(*this, &C4StartupOptionsDlg::KeySelDialog::KeyDown), C4CustomKey::PRIO_PlrControl);
pKeyListener = new C4KeyBinding(
C4KeyCodeEx(KEY_Any, KEYS_None),
"DefineKey",
KEYSCOPE_Gui,
new C4GUI::DlgKeyCBPassKey<C4StartupOptionsDlg::KeySelDialog>(
*this,
&C4StartupOptionsDlg::KeySelDialog::KeyDown,
&C4StartupOptionsDlg::KeySelDialog::KeyUp
),
C4CustomKey::PRIO_PlrControl
);
}
StdStrBuf C4StartupOptionsDlg::KeySelDialog::GetDlgMessage(const C4PlayerControlAssignment *assignment, const C4PlayerControlAssignmentSet *assignment_set)
@ -183,7 +194,61 @@ C4StartupOptionsDlg::KeySelDialog::~KeySelDialog()
delete pKeyListener;
}
bool C4StartupOptionsDlg::KeySelDialog::KeyDown(const C4KeyCodeEx &key)
void C4StartupOptionsDlg::KeySelDialog::MouseInput(C4GUI::CMouse& rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
{
// Original action
C4GUI::MessageDialog::MouseInput(rMouse, iButton, iX, iY, dwKeyParam);
// Find out to where the input was made (code duplication with C4GUI::Window::MouseInput)
// get client pos
C4Rect &rcClientRect = GetClientRect(), &rcBounds = GetBounds();
iX -= rcClientRect.x - rcBounds.x; iY -= rcClientRect.y - rcBounds.y;
// forward to topmost child element
for (Element *pChild = pLast; pChild; pChild = pChild->GetPrev())
if (pChild->fVisible && pChild->GetBounds().Contains(iX, iY))
{
if (dynamic_cast<C4GUI::Label*>(pChild))
break;
else
return;
}
// Only process the input event if the user certainly didn't click a button or anything…
// Logic duplication of C4PlayerControl::DoMouseInput (and C4MouseControl::Move for the wheel_dir.) There has to be a better way. :(
uint8_t mouseevent_code;
int wheel_dir = 0;
if (iButton == C4MC_Button_Wheel) wheel_dir = (short)(dwKeyParam >> 16);
switch (iButton)
{
case C4MC_Button_LeftUp:
case C4MC_Button_RightUp:
case C4MC_Button_MiddleUp:
case C4MC_Button_X1Up:
case C4MC_Button_X2Up:
case C4MC_Button_None:
return;
case C4MC_Button_LeftDown: mouseevent_code = KEY_MOUSE_ButtonLeft; break;
case C4MC_Button_LeftDouble: mouseevent_code = KEY_MOUSE_ButtonLeftDouble; break;
case C4MC_Button_RightDown: mouseevent_code = KEY_MOUSE_ButtonRight; break;
case C4MC_Button_RightDouble: mouseevent_code = KEY_MOUSE_ButtonRightDouble; break;
case C4MC_Button_MiddleDown: mouseevent_code = KEY_MOUSE_ButtonMiddle; break;
case C4MC_Button_MiddleDouble: mouseevent_code = KEY_MOUSE_ButtonMiddleDouble; break;
case C4MC_Button_X1Down: mouseevent_code = KEY_MOUSE_ButtonX1; break;
case C4MC_Button_X1Double: mouseevent_code = KEY_MOUSE_ButtonX1Double; break;
case C4MC_Button_X2Down: mouseevent_code = KEY_MOUSE_ButtonX2; break;
case C4MC_Button_X2Double: mouseevent_code = KEY_MOUSE_ButtonX2Double; break;
case C4MC_Button_Wheel:
if (!wheel_dir) return;
mouseevent_code = (wheel_dir > 0) ? KEY_MOUSE_Wheel1Up : KEY_MOUSE_Wheel1Down; break;
}
C4KeyCodeEx key{KEY_Mouse(0, mouseevent_code), KEYS_None};
if (dwKeyParam & MK_CONTROL) key.dwShift |= KEYS_Control;
if (dwKeyParam & MK_SHIFT) key.dwShift |= KEYS_Shift;
if (dwKeyParam & MK_ALT) key.dwShift |= KEYS_Alt;
KeyDown(key);
}
bool C4StartupOptionsDlg::KeySelDialog::KeyPress(const C4KeyCodeEx &key, bool fDown)
{
// safety
if (!assignment || !assignment_set) return false;
@ -200,6 +265,13 @@ bool C4StartupOptionsDlg::KeySelDialog::KeyDown(const C4KeyCodeEx &key)
{
if (!assignment_set->HasKeyboard()) return false;
}
// FIXME: There doesn't seem to be any kind of KEY_IsModifier function…
switch (key.Key) {
case K_CONTROL_L: case K_SHIFT_L: case K_ALT_L:
case K_CONTROL_R: case K_SHIFT_R: case K_ALT_R:
if (fDown)
return false;
}
// okay, use it
this->key=key;
Close(true);

View File

@ -165,7 +165,10 @@ private:
static C4GUI::Icons GetDlgIcon(const class C4PlayerControlAssignmentSet *assignment_set);
protected:
bool KeyDown(const C4KeyCodeEx &key);
bool KeyDown(const C4KeyCodeEx &key) { return KeyPress(key, true); };
bool KeyUp(const C4KeyCodeEx &key) { return KeyPress(key, false); };
bool KeyPress(const C4KeyCodeEx &key, bool fDown);
void MouseInput(C4GUI::CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam) override;
public:
KeySelDialog(const class C4PlayerControlAssignment *assignment, const class C4PlayerControlAssignmentSet *assignment_set);
~KeySelDialog() override;