feat(menu): navegació del menú de servei amb sticks
This commit is contained in:
1 parent
2c1c1a442b
commit
fddea0c449
2 files changed
+76
No files matched your search
@@ -467,6 +467,63 @@ void ServiceMenu::playAcceptSound() {
|
||||
Audio::get()->playSound(UiConfig::get().menuAcceptSound(), Audio::Group::INTERFACE);
|
||||
}
|
||||
|
||||
void ServiceMenu::handleGamepadAxisMotion(const SDL_GamepadAxisEvent& ev) {
|
||||
// Llindars amb histèresi: cal travessar STICK_THRESHOLD per "entrar" a
|
||||
// un extrem, però només es torna a la zona neutra quan baixa de
|
||||
// STICK_RELEASE. Així evitem que petits tremolors al voltant del
|
||||
// llindar facin spam d'events. Valors triats per donar la mateixa
|
||||
// sensació que el stick del jugador (deadzone=12000) però una mica
|
||||
// més estrictes per a la navegació discreta del menú.
|
||||
constexpr Sint16 STICK_THRESHOLD = 16000;
|
||||
constexpr Sint16 STICK_RELEASE = 8000;
|
||||
|
||||
std::int8_t* zone = nullptr;
|
||||
bool horizontal = false;
|
||||
switch (ev.axis) {
|
||||
case SDL_GAMEPAD_AXIS_LEFTX:
|
||||
zone = &lx_zone_;
|
||||
horizontal = true;
|
||||
break;
|
||||
case SDL_GAMEPAD_AXIS_LEFTY:
|
||||
zone = &ly_zone_;
|
||||
horizontal = false;
|
||||
break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTX:
|
||||
zone = &rx_zone_;
|
||||
horizontal = true;
|
||||
break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTY:
|
||||
zone = &ry_zone_;
|
||||
horizontal = false;
|
||||
break;
|
||||
default:
|
||||
return; // Ignorem L2/R2 i la resta.
|
||||
}
|
||||
|
||||
// Càlcul de la zona nova: si el valor està més enllà del llindar fort,
|
||||
// entra a l'extrem; si està dins de la zona morta, torna a 0; altrament
|
||||
// manté la zona prèvia (banda d'histèresi).
|
||||
std::int8_t new_zone = *zone;
|
||||
if (ev.value > STICK_THRESHOLD) {
|
||||
new_zone = +1;
|
||||
} else if (ev.value < -STICK_THRESHOLD) {
|
||||
new_zone = -1;
|
||||
} else if (std::abs(ev.value) < STICK_RELEASE) {
|
||||
new_zone = 0;
|
||||
}
|
||||
if (new_zone == *zone) { return; }
|
||||
*zone = new_zone;
|
||||
if (new_zone == 0) { return; } // Soltar el stick no dispara res.
|
||||
|
||||
if (horizontal) {
|
||||
activateCurrent(new_zone);
|
||||
playAcceptSound();
|
||||
} else {
|
||||
moveCursor(new_zone);
|
||||
playSelectSound();
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceMenu::handleGamepadButtonDown(const SDL_GamepadButtonEvent& ev) {
|
||||
// El botó SERVICE (per defecte BACK; remapejable per dispositiu via
|
||||
// `GamepadBindings`) tanca el menú sencer. Cada mando pot tenir el
|
||||
@@ -570,6 +627,11 @@ auto ServiceMenu::handleEvent(const SDL_Event& ev) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ev.type == SDL_EVENT_GAMEPAD_AXIS_MOTION) {
|
||||
handleGamepadAxisMotion(ev.gaxis);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ev.type != SDL_EVENT_KEY_DOWN) { return false; }
|
||||
|
||||
const auto SC = ev.key.scancode;
|
||||
|
||||
Reference in new issue
Block a user