feat(service_menu): triggers L2/R2 navegables + so al rebind
El menu de servei nomes processava AXIS_MOTION dels sticks i descartava els triggers. Com SDL3 mai emet button events per a L2/R2 (nomes axis), rebindar FIRE o ACCEL a un trigger feia que no funcionaren al menu, fins i tot estant correctament al joc per via del poll de Input::checkTriggerInput. Afegim edge-detect dels dos triggers al handleGamepadAxis i, quan creuen el llindar, mirem si el codi virtual (100=L2, 101=R2) coincideix amb el binding de FIRE → activateCurrent, o ACCEL → popPage. Estat held per trigger per evitar repeticions mentre es mante premut. DefineInputs ara reprodueix el so accept del menu en cada captura valida, que estava silent i no donava feedback al rebind. Tambe extraiem processStickX/Y i processTriggerEdge per mantenir handleGamepadAxis com a dispatcher i sota el llindar de complexitat cognitiva del clang-tidy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -818,6 +818,9 @@ namespace System {
|
||||
// Llindar de stick per a navegacio de menu (mig camp del rang ±32767).
|
||||
// Mes baix que el del joc (30000) per a una resposta mes agil al menu.
|
||||
constexpr Sint16 MENU_STICK_THRESHOLD = 16384;
|
||||
// Llindar de trigger (mateix valor que MENU_TRIGGER_THRESHOLD, que
|
||||
// és private). Edge a partir del 50% del rang.
|
||||
constexpr Sint16 MENU_TRIGGER_THRESHOLD = 16384;
|
||||
|
||||
// Retorna true si el codi de boto SDL coincideix amb l'accio
|
||||
// configurada per algun dels dos jugadors (es a dir, el boto te el
|
||||
@@ -914,36 +917,69 @@ namespace System {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ServiceMenu::processStickX(Sint16 val) {
|
||||
const bool LEFT_NOW = val < -MENU_STICK_THRESHOLD;
|
||||
const bool RIGHT_NOW = val > MENU_STICK_THRESHOLD;
|
||||
if (LEFT_NOW && !stick_left_held_) {
|
||||
changeValue(-1);
|
||||
}
|
||||
if (RIGHT_NOW && !stick_right_held_) {
|
||||
changeValue(+1);
|
||||
}
|
||||
stick_left_held_ = LEFT_NOW;
|
||||
stick_right_held_ = RIGHT_NOW;
|
||||
}
|
||||
|
||||
void ServiceMenu::processStickY(Sint16 val) {
|
||||
const bool UP_NOW = val < -MENU_STICK_THRESHOLD;
|
||||
const bool DOWN_NOW = val > MENU_STICK_THRESHOLD;
|
||||
if (UP_NOW && !stick_up_held_) {
|
||||
moveCursor(-1);
|
||||
}
|
||||
if (DOWN_NOW && !stick_down_held_) {
|
||||
moveCursor(+1);
|
||||
}
|
||||
stick_up_held_ = UP_NOW;
|
||||
stick_down_held_ = DOWN_NOW;
|
||||
}
|
||||
|
||||
// Edge-detect d'un trigger: si creua el llindar amunt, despatxa
|
||||
// ENTER/BACK segons el binding (FIRE/ACCEL) que apunta al codi
|
||||
// virtual del trigger (100 = L2, 101 = R2).
|
||||
void ServiceMenu::processTriggerEdge(SDL_JoystickID which, Sint16 val, int virtual_button, bool& held) {
|
||||
const bool NOW = val > MENU_TRIGGER_THRESHOLD;
|
||||
if (NOW && !held) {
|
||||
if (buttonMatchesAction(which, virtual_button, InputAction::SHOOT)) {
|
||||
activateCurrent();
|
||||
} else if (buttonMatchesAction(which, virtual_button, InputAction::THRUST)) {
|
||||
popPage();
|
||||
}
|
||||
}
|
||||
held = NOW;
|
||||
}
|
||||
|
||||
auto ServiceMenu::handleGamepadAxis(const SDL_Event& event) -> bool {
|
||||
const auto AXIS = static_cast<SDL_GamepadAxis>(event.gaxis.axis);
|
||||
const Sint16 VAL = event.gaxis.value;
|
||||
if (AXIS == SDL_GAMEPAD_AXIS_LEFTX) {
|
||||
const bool LEFT_NOW = VAL < -MENU_STICK_THRESHOLD;
|
||||
const bool RIGHT_NOW = VAL > MENU_STICK_THRESHOLD;
|
||||
if (LEFT_NOW && !stick_left_held_) {
|
||||
changeValue(-1);
|
||||
}
|
||||
if (RIGHT_NOW && !stick_right_held_) {
|
||||
changeValue(+1);
|
||||
}
|
||||
stick_left_held_ = LEFT_NOW;
|
||||
stick_right_held_ = RIGHT_NOW;
|
||||
return true;
|
||||
switch (AXIS) {
|
||||
case SDL_GAMEPAD_AXIS_LEFTX:
|
||||
processStickX(VAL);
|
||||
return true;
|
||||
case SDL_GAMEPAD_AXIS_LEFTY:
|
||||
processStickY(VAL);
|
||||
return true;
|
||||
// Triggers L2/R2: SDL3 nomes emet AXIS_MOTION, no button events.
|
||||
// Per poder rebindar FIRE/ACCEL als triggers, sintetitzem aqui
|
||||
// la pulsacio amb edge-detect i la passem pel mateix flux.
|
||||
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER:
|
||||
processTriggerEdge(event.gaxis.which, VAL, Input::TRIGGER_L2_AS_BUTTON, trigger_l2_held_);
|
||||
return true;
|
||||
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER:
|
||||
processTriggerEdge(event.gaxis.which, VAL, Input::TRIGGER_R2_AS_BUTTON, trigger_r2_held_);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (AXIS == SDL_GAMEPAD_AXIS_LEFTY) {
|
||||
const bool UP_NOW = VAL < -MENU_STICK_THRESHOLD;
|
||||
const bool DOWN_NOW = VAL > MENU_STICK_THRESHOLD;
|
||||
if (UP_NOW && !stick_up_held_) {
|
||||
moveCursor(-1);
|
||||
}
|
||||
if (DOWN_NOW && !stick_down_held_) {
|
||||
moveCursor(+1);
|
||||
}
|
||||
stick_up_held_ = UP_NOW;
|
||||
stick_down_held_ = DOWN_NOW;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ServiceMenu::computeTargetHeight() const -> float {
|
||||
|
||||
@@ -100,6 +100,11 @@ namespace System {
|
||||
auto handleKeyDown(const SDL_Event& event) -> bool;
|
||||
auto handleGamepadButton(const SDL_Event& event) -> bool;
|
||||
auto handleGamepadAxis(const SDL_Event& event) -> bool;
|
||||
// Helpers per a cada eix; permeten que handleGamepadAxis es quedi
|
||||
// com a dispatcher i no bote el llindar de complexitat.
|
||||
void processStickX(Sint16 val);
|
||||
void processStickY(Sint16 val);
|
||||
void processTriggerEdge(SDL_JoystickID which, Sint16 val, int virtual_button, bool& held);
|
||||
|
||||
void buildRootPage();
|
||||
[[nodiscard]] auto buildVideoPage() -> Page;
|
||||
@@ -162,6 +167,11 @@ namespace System {
|
||||
bool stick_right_held_ = false;
|
||||
bool stick_up_held_ = false;
|
||||
bool stick_down_held_ = false;
|
||||
// Edge-detect dels triggers L2/R2 com a botons virtuals. SDL3 no
|
||||
// emet button events per als triggers; els llegim com a axis i
|
||||
// sintetitzem una pulsacio quan creuen el llindar.
|
||||
bool trigger_l2_held_ = false;
|
||||
bool trigger_r2_held_ = false;
|
||||
|
||||
static std::unique_ptr<ServiceMenu> instance;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user