add hat support

This commit is contained in:
David Griswold 2026-02-07 15:50:30 +03:00
parent 43ead51b50
commit daa37dfd99
3 changed files with 57 additions and 34 deletions

View File

@ -141,17 +141,23 @@ QString ConfigureControllerHotkeys::CleanSequence(QString controller_keyseq) {
if (controller_keyseq.isEmpty())
return controller_keyseq;
QStringList keys = controller_keyseq.split(QStringLiteral("||"));
QString output = QStringLiteral("Button ").append(
keys.value(0).split(QStringLiteral(",")).value(0).split(QStringLiteral(":")).value(1));
Common::ParamPackage p1 = Common::ParamPackage(keys.value(0).toStdString());
QString output;
if (p1.Has("hat")) {
output = QString::fromStdString("Hat " + p1.Get("hat", "") + " " + p1.Get("direction", ""));
} else if (p1.Has("button")) {
output = QString::fromStdString("Button " + p1.Get("button", ""));
}
if (keys.length() > 1) {
output.append(QStringLiteral(" + Button "))
.append(keys.value(1)
.split(QStringLiteral(","))
.value(0)
.split(QStringLiteral(":"))
.value(1));
output.append(QStringLiteral(" + "));
p1 = Common::ParamPackage(keys.value(1).toStdString());
if (p1.Has("hat")) {
output +=
QString::fromStdString("Hat " + p1.Get("hat", "") + " " + p1.Get("direction", ""));
} else if (p1.Has("button")) {
output += QString::fromStdString("Button " + p1.Get("button", ""));
}
}
return output;
}

View File

@ -55,39 +55,36 @@ void ControllerSequenceDialog::LaunchPollers() {
Common::ParamPackage params;
for (auto& poller : device_pollers) {
params = poller->GetNextInput();
if (params.Has("engine") && params.Has("button")) { // for now, no analog inputs
if (params.Has("engine") &&
(params.Has("hat") || params.Has("button"))) { // for now, no analog inputs
std::cerr << "controller hotkey event detected: " + params.Serialize() << std::endl;
if (params.Has("down")) {
std::cerr << "button " + params.Get("button", "") + " down" << std::endl;
downCount++;
if (downCount > 2) {
// ignore third and fourth and fifth buttons
} else if (downCount == 1) {
if (downCount == 1) {
// either the first press, or the first new press
key_sequence = QStringLiteral("");
params1 = params;
params2 = Common::ParamPackage();
textBox->setText(ConfigureControllerHotkeys::CleanSequence(
QString::fromStdString(params1.Serialize())) +
key_sequence = QString::fromStdString(params1.Serialize());
textBox->setText(ConfigureControllerHotkeys::CleanSequence(key_sequence) +
QStringLiteral("..."));
} else if (downCount == 2) {
// this is a second button while the first one is held down,
// go ahead and set the key_sequence as the chord and clear params
} else if (downCount == 2 && !params2.Has("engine")) {
// this is a second button, currently only one button saved, so save it
params2 = params;
key_sequence = QString::fromStdString(params1.Serialize() + "||" +
params2.Serialize());
textBox->setText(ConfigureControllerHotkeys::CleanSequence(key_sequence));
}
// if downCount == 3 or more, just ignore them - we have saved the first two
// presses
} else { // button release
downCount--;
std::cerr << "button " + params.Get("button", "") + " up" << std::endl;
if (downCount == 0) {
// all released, clear all saved params
if (downCount <= 0) {
// once all buttons are released, clear the params so the user can try again
// if need be
params1 = Common::ParamPackage();
params2 = Common::ParamPackage();
}
if (key_sequence.isEmpty()) {
key_sequence = QString::fromStdString(params.Serialize());
textBox->setText(ConfigureControllerHotkeys::CleanSequence(key_sequence));
}
}
}
}

View File

@ -187,7 +187,8 @@ public:
state.buttons[button] = value;
}
// no longer used, at least as a test
// no longer used - creating state breaks hotkey detection, so
// poll sdl directly below
bool GetButton(int button) const {
std::lock_guard lock{mutex};
return state.buttons.at(button);
@ -233,11 +234,18 @@ public:
state.hats[hat] = direction;
}
// no longer used, poll directly instead
bool GetHatDirection(int hat, Uint8 direction) const {
std::lock_guard lock{mutex};
return (state.hats.at(hat) & direction) != 0;
}
bool GetHatDirectionDirect(int hat, Uint8 direction) const {
if (!sdl_joystick)
return false;
return SDL_JoystickGetHat(sdl_joystick.get(), hat) == direction;
}
void SetAccel(const float x, const float y, const float z) {
std::lock_guard lock{mutex};
state.accel.x = x;
@ -636,7 +644,7 @@ public:
: joystick(std::move(joystick_)), hat(hat_), direction(direction_) {}
bool GetStatus() const override {
return joystick->GetHatDirection(hat, direction);
return joystick->GetHatDirectionDirect(hat, direction);
}
private:
@ -897,6 +905,9 @@ SDLState::~SDLState() {
Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event,
const bool down = false) {
Common::ParamPackage params({{"engine", "sdl"}});
if (down) {
params.Set("down", "1");
}
auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
switch (event.type) {
case SDL_JOYAXISMOTION: {
@ -936,14 +947,16 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve
case SDL_HAT_RIGHT:
params.Set("direction", "right");
break;
case SDL_HAT_CENTERED:
params.Set("direction", "centered");
break;
default:
return {};
}
break;
}
}
if (down)
params.Set("down", 1);
return params;
}
@ -1016,11 +1029,18 @@ public:
axis_event_count.clear();
}
}
case SDL_JOYBUTTONDOWN:
down = true;
case SDL_JOYBUTTONUP:
case SDL_JOYHATMOTION:
return SDLEventToButtonParamPackage(state, event, down);
break;
case SDL_JOYBUTTONDOWN:
return SDLEventToButtonParamPackage(state, event, true);
break;
case SDL_JOYBUTTONUP:
return SDLEventToButtonParamPackage(state, event, false);
break;
case SDL_JOYHATMOTION:
return SDLEventToButtonParamPackage(state, event,
event.jhat.value == SDL_HAT_CENTERED);
break;
}
}
return {};