Skip to content

Start the option rows under the tab bar and pin Return to the bottom - #473

Merged
tomconder merged 4 commits into
mainfrom
feat/menu-row-layout
Sep 3, 2026
Merged

Start the option rows under the tab bar and pin Return to the bottom#473
tomconder merged 4 commits into
mainfrom
feat/menu-row-layout

Conversation

@tomconder

Copy link
Copy Markdown
Owner

What

Both option tabs start their rows under the tab strip instead of below a spacer, and Return sits at the bottom of the column on both, at the same y.

ui::pinMenuRowToBottom() does the anchoring: an auto top margin takes the leftover space, and a flex basis of one row height reserves the row.

The basis is the part that matters. makeMenuRow calls YGNodeStyleSetFlex(child, 1.F), which leaves a flex basis of 0, and that wins over a height. Setting only the height collapsed Return to 0 px: the label still drew at the row's top edge, so it looked right, but the highlight quad had no height and the mouse had nothing to hit. Logging the node heights showed 82 81 82 81 82 82 0 in a 561 px column. With the basis set they come out 80 80 80 79 80 80 82.

Spacing scales with resolution

Row heights track the menu font (menuRowHeight() = 3.4 x the font size) rather than a flat 110 px, and are applied in recalculateLayout(), where the window width is known, so a resize carries them. At 1280x720 the old fixed height let seven rows fill the column and Return overlapped the Shadow Map dots.

makeMenuRow keeps its 110 px cap, so the intro and exit menus are unchanged.

The Keyboard tab fills its column, so Reset to Defaults carries a bottom margin that keeps it off Return.

Testing

Built and driven with synthesised input at two window sizes.

Return y, both tabs Reset to Return collision
1920x1080 (font 32) 1008 95 px none
1280x720 (font 24) 672 66 px none
  • Down x6 on Display and Down x8 on Keyboard put the selection on Return, which takes the red fill and white border.
  • Hovering Return with the mouse shows the grey hover fill, and clicking it returns to the intro menu.
  • pre-commit run is clean on the three changed files.

2560 and above (font 48, rows capped at 163 px) is untested, since no display here reaches it.

Both tabs dropped the spacer above their rows, so the list starts under
the tab strip. Return is pinned to the bottom by pinMenuRowToBottom():
an auto top margin takes the leftover space, and a flex basis of one row
height reserves the row so the siblings cannot grow into it. Setting
only a height does not work, because makeMenuRow leaves a flex basis of
0 that wins over it, which collapsed the row and lost its highlight.

Row heights now track the menu font instead of a flat 110 px, and are
applied in recalculateLayout() where the window width is known, so they
follow a resize. At 1280x720 the old fixed height let the rows fill the
column and Return collided with the Shadow Map dots.

The Keyboard tab fills its column, so Reset to Defaults carries a bottom
margin to keep it clear of Return.
@github-actions github-actions Bot added the game Game changes label Sep 2, 2026
The pad reports a second down/up 3-6ms after a button is really released.
That extra edge fired the action twice: a checkbox toggled off and back on,
and Return closed the options screen and then reopened it from the menu
underneath.

The old latch cleared the moment the action stopped being held, and the
bounce lands after the release, so it went straight through. Anchor the
latch to the release instead: hold it until the action has been let go for
a continuous 50ms, well above the bounce and well under a deliberate second
press.

Cursor drift no longer takes the device from the gamepad either. A resting
hand clears half a pixel, which flipped the active device to keyboard mid
press and let the driver's aliased key through as a second edge. It now
waits for the gamepad grace, while a mouse click still switches at once.

Menus arm the wait-for-release when a screen above them closes. Both menus
set wasActiveLastFrame unconditionally, so the flag was never false on the
frame the options screen handed input back and the guard never armed.
@github-actions github-actions Bot added the sponge Sponge engine changes label Sep 3, 2026
The tab set wasActiveLastFrame unconditionally, so the flag was never false
on the frame a capture handed input back and the wait-for-release guard
never armed. Binding a key that also confirms, Enter or Space, left the key
still held as the row went live again and the menu reopened the capture on
the next edge.

Gate the guard and the flag on the same condition the actions already use,
matching the intro and exit menus.
MSVC warns C4458 on the local, and the CI build turns warnings into errors.
Nothing shadows the base class member now, and takesInput says what the flag
means: this menu is the one reading input this frame.
@tomconder
tomconder merged commit 21e0427 into main Sep 3, 2026
9 checks passed
@tomconder
tomconder deleted the feat/menu-row-layout branch September 3, 2026 04:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

game Game changes sponge Sponge engine changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant