forked from Ports/goldeneye-pc-port
Options overlay: native gamepad support (Select / D-pad / A / B / Start).
Controller-only machines (Steam Deck) had no way to open or navigate the F10 options overlay -- it was keyboard+mouse only. Now: - Select (BACK) rising edge toggles the overlay, tracked across both the open and closed poll paths (padSelectPrev) so a held button cannot re-toggle on the transition. BACK is read nowhere else in the port. - While open, D-pad or left stick up/down moves the selection, A/X step forward (the Enter equivalent), B/Y step back, Start closes. The gamepad bits are OR-ed into the existing keyboard edge logic, so repeat/clamp/ scroll behaviour is identical; input.c already swallows pad 0 while the overlay is open, so nothing reaches the game. - inputPadButton/inputPadAxis accessors expose raw SDL pad state to the overlay (unaffected by our logic-layer swallow). Smoke-tested headless with GE_OPTIONSOVERLAY=1 and no pad attached.
This commit is contained in:
1 parent
97ba1e9b07
commit
72af96cf0d
3 files changed
+63
-7
No files matched your search
@@ -55,6 +55,12 @@ int inputReleaseCapture(void);
|
||||
* owns the mouse. Safe to call every poll. */
|
||||
void inputSuspendForOverlay(void);
|
||||
|
||||
/* Raw gamepad state for controller idx (the F10 options overlay's gamepad
|
||||
* navigation). Unaffected by the overlay's pad-swallow, which happens at our
|
||||
* logic layer, not SDL's. No pad open -> 0. */
|
||||
int inputPadButton(int idx, SDL_GameControllerButton b);
|
||||
short inputPadAxis(int idx, SDL_GameControllerAxis a);
|
||||
|
||||
/* Queue a mouse-wheel weapon-cycle input (one short A-button press). Sign is
|
||||
* ignored -- GE only cycles forward on a bare A edge. */
|
||||
void inputPostWheel(int notches);
|
||||
|
||||
+32
-3
@@ -275,6 +275,7 @@ static int connectedMask = 0x1; /* controller 0 always present */
|
||||
|
||||
static SDL_GameController *pads[MAX_PADS];
|
||||
static int padShoulderPrev[MAX_PADS]; /* LB/RB edge state for weapon cycling */
|
||||
static int padSelectPrev = 0; /* Select (BACK) edge: overlay toggle */
|
||||
|
||||
static int mouseEnabled = 1;
|
||||
static int mouseGrabbed = 1; /* released while the window is unfocused */
|
||||
@@ -748,10 +749,17 @@ unsigned inputComputePad(int idx, signed char *stick_x, signed char *stick_y)
|
||||
}
|
||||
|
||||
/* F10 options overlay: while it is open, controller 0 is fully swallowed
|
||||
* (neutral pad, no stick) and the nav keys / wheel drive the overlay
|
||||
* instead. Mirrors the WI-1 "cursor free in a stage -> withhold input"
|
||||
* pattern. Controllers 1-3 are untouched. */
|
||||
* (neutral pad, no stick) and the nav keys / wheel / gamepad drive the
|
||||
* overlay instead. Mirrors the WI-1 "cursor free in a stage -> withhold
|
||||
* input" pattern. Controllers 1-3 are untouched. */
|
||||
if (idx == 0 && optionsOverlayIsOpen()) {
|
||||
/* Select closes the overlay. padSelectPrev is tracked on this path
|
||||
* and the open path below alike, so a button held across the
|
||||
* transition cannot immediately re-toggle it. */
|
||||
int selNow = pads[0] ? SDL_GameControllerGetButton(pads[0],
|
||||
SDL_CONTROLLER_BUTTON_BACK) : 0;
|
||||
if (selNow && !padSelectPrev) optionsOverlayToggle();
|
||||
padSelectPrev = selNow;
|
||||
optionsOverlayHandleInput();
|
||||
if (stick_x) *stick_x = 0;
|
||||
if (stick_y) *stick_y = 0;
|
||||
@@ -1158,6 +1166,15 @@ unsigned inputComputePad(int idx, signed char *stick_x, signed char *stick_y)
|
||||
button |= GE_CONT_LEFT;
|
||||
if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
|
||||
button |= GE_CONT_RIGHT;
|
||||
|
||||
/* Select (BACK) opens the F10 options overlay -- the gamepad
|
||||
* equivalent of the F10 key for controller-only machines (Steam
|
||||
* Deck). The game never reads BACK, so nothing is withheld. */
|
||||
{
|
||||
int selNow = SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_BACK);
|
||||
if (selNow && !padSelectPrev) optionsOverlayToggle();
|
||||
padSelectPrev = selNow;
|
||||
}
|
||||
}
|
||||
|
||||
if (sx > STICK_MAX) sx = STICK_MAX;
|
||||
@@ -1256,6 +1273,18 @@ int inputReleaseCapture(void)
|
||||
* stage) would persist and the mouse UI would be unusable. Force the cursor
|
||||
* free + visible every poll; the normal reconcile resumes once the overlay
|
||||
* closes and the early-return no longer fires. */
|
||||
int inputPadButton(int idx, SDL_GameControllerButton b)
|
||||
{
|
||||
if (idx < 0 || idx >= MAX_PADS || !pads[idx]) return 0;
|
||||
return SDL_GameControllerGetButton(pads[idx], b);
|
||||
}
|
||||
|
||||
short inputPadAxis(int idx, SDL_GameControllerAxis a)
|
||||
{
|
||||
if (idx < 0 || idx >= MAX_PADS || !pads[idx]) return 0;
|
||||
return SDL_GameControllerGetAxis(pads[idx], a);
|
||||
}
|
||||
|
||||
void inputSuspendForOverlay(void)
|
||||
{
|
||||
if (mouseGrabbed) {
|
||||
|
||||
@@ -565,11 +565,32 @@ void optionsOverlayHandleInput(void)
|
||||
int lmb = (mb & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0;
|
||||
int rmb = (mb & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0;
|
||||
|
||||
int up = ks[SDL_SCANCODE_UP] || ks[SDL_SCANCODE_KP_8];
|
||||
int dn = ks[SDL_SCANCODE_DOWN] || ks[SDL_SCANCODE_KP_2];
|
||||
int lf = ks[SDL_SCANCODE_LEFT] || ks[SDL_SCANCODE_KP_4];
|
||||
/* Gamepad navigation (controller-only machines, e.g. Steam Deck): the
|
||||
* D-pad or left stick moves the selection; A/X step forward (the Enter
|
||||
* equivalent), B/Y step back; Start closes. OR-ed into the same edge
|
||||
* logic as the keyboard, so repeat/clamp/scroll behaviour is identical.
|
||||
* input.c swallows the pad while we are open, so none of this reaches
|
||||
* the game. (Select also closes -- handled in input.c's toggle, which
|
||||
* runs before this one.) */
|
||||
int gUp = inputPadButton(0, SDL_CONTROLLER_BUTTON_DPAD_UP)
|
||||
|| inputPadAxis(0, SDL_CONTROLLER_AXIS_LEFTY) < -12000;
|
||||
int gDn = inputPadButton(0, SDL_CONTROLLER_BUTTON_DPAD_DOWN)
|
||||
|| inputPadAxis(0, SDL_CONTROLLER_AXIS_LEFTY) > 12000;
|
||||
int up = ks[SDL_SCANCODE_UP] || ks[SDL_SCANCODE_KP_8] || gUp;
|
||||
int dn = ks[SDL_SCANCODE_DOWN] || ks[SDL_SCANCODE_KP_2] || gDn;
|
||||
int lf = ks[SDL_SCANCODE_LEFT] || ks[SDL_SCANCODE_KP_4]
|
||||
|| inputPadButton(0, SDL_CONTROLLER_BUTTON_B)
|
||||
|| inputPadButton(0, SDL_CONTROLLER_BUTTON_Y);
|
||||
int rt = ks[SDL_SCANCODE_RIGHT] || ks[SDL_SCANCODE_KP_6]
|
||||
|| ks[SDL_SCANCODE_RETURN] || ks[SDL_SCANCODE_KP_ENTER];
|
||||
|| ks[SDL_SCANCODE_RETURN] || ks[SDL_SCANCODE_KP_ENTER]
|
||||
|| inputPadButton(0, SDL_CONTROLLER_BUTTON_A)
|
||||
|| inputPadButton(0, SDL_CONTROLLER_BUTTON_X);
|
||||
|
||||
static int prevStart = 0; /* not reset while closed: a Start held across
|
||||
close must not re-close on the next open */
|
||||
int startNow = inputPadButton(0, SDL_CONTROLLER_BUTTON_START);
|
||||
if (startNow && !prevStart) optionsOverlayToggle(); /* Start closes */
|
||||
prevStart = startNow;
|
||||
|
||||
/* ---- keyboard / D-pad nav (clamped at the ends; scroll follows) ---- */
|
||||
if (up && !prevUp && s_sel > 0) s_sel--;
|
||||
|
||||
Reference in new issue
Block a user