feat(input): mouse navigation foundations + main menu support#414
Draft
adstep wants to merge 1 commit into
Draft
feat(input): mouse navigation foundations + main menu support#414adstep wants to merge 1 commit into
adstep wants to merge 1 commit into
Conversation
b84bed6 to
5c0b4c0
Compare
Adds optional mouse support, gated behind a new EnableMouseInput config
flag that defaults off. Keyboard, gamepad, and pad input are unchanged
on every screen.
Foundations:
- engine::space::{LogicalPos, WindowPos} newtypes + to_logical conversion
so coordinate spaces can't be silently confused.
- engine::input::{PointerEvent, PointerKind, MouseButton} plus a new
InputSource::Mouse variant.
- winit CursorMoved / CursorLeft / MouseInput / MouseWheel routed through
a single app::dispatch_pointer_event seam. Pixel-source wheel scrolls
(touchpads) normalize to lines via a PIXEL_PER_LINE = 20.0 heuristic.
- ShellState.pointer_pos_logical cache, refreshed on resize so screens
never see stale projections.
Main menu:
- Hover over a row highlights it silently (no chirp on every mouse pixel).
- Left-click on a row launches that row.
- Right-click anywhere acts as back.
- Cursor swaps to a magenta hover variant when over an interactive row.
Themed cursor:
- Custom navigate-style cursor PNG with a default-theme magenta hover
variant, hotspot pinned at the visual tip.
- scripts/gen_cursors.py rebuilds both variants from the source asset,
auto-detects the hotspot, and syncs into target/<profile>/assets so
tweaks don't need a cargo rebuild.
- Source artwork attributed to zky.icon / Flaticon beside the asset.
- Honors the existing HideMouseCursor preference.
Reusable helpers (used by the main menu, ready for other screens):
- menu_list::item_rects pairs hit-rect math with the actor builder so
layout and hit testing share constants.
- components::shared::menu_pointer::MenuPointer encapsulates hover/click
bookkeeping for list-style screens.
- components::shared::hitbox::{HitRect, hit_test} geometry primitives.
Adds 11 passing tests across hitbox, menu_list, menu_pointer, and the
main-menu modules.
5c0b4c0 to
b8be017
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Every menu in DeadSync is key/gamepad/pad-only today, but a lot of casual users (and anyone running on a laptop) reasonably expect to be able to click on UI elements. This change adds the foundations for mouse input and lights it up on the main menu so the pattern is proven end-to-end. Wider screen coverage will follow in separate PRs.
Approach
Mouse augments the existing input system rather than replacing it. The shape:
InputSource::Mousevariant lets screens synthesize regularInputEvents for clicks where it's natural. The existing per-screenhandle_inputpaths keep owning confirm/back semantics.Vec<HitRect>each frame next to their actor list and callhit_testto map pointer position to a row id. The same helper that lays out the visible labels (menu_list::item_rects) also produces the rects, so the two can't drift.app::dispatch_pointer_eventroutes each event to the active screen and gets back both the action to dispatch and a "pointer is over something interactive" flag. The flag drives a cursor swap to a magenta hover variant. Screens that haven't opted in are no-ops.Mouse input is gated behind an
EnableMouseInputconfig flag (default off) so this can land without affecting any existing setup. Keyboard, gamepad, and pad input are untouched on every screen.What's in this PR
Foundations
engine::space::{LogicalPos, WindowPos}newtypes +WindowPos::to_logicalso coordinate spaces can't be silently confused.engine::input::{PointerEvent, PointerKind, MouseButton}plus a newInputSource::Mousevariant.winit::WindowEvent::{CursorMoved, CursorLeft, MouseInput, MouseWheel}wired throughapp::dispatch_pointer_event.ShellState.pointer_pos_logicalcache, refreshed on resize so screens never see stale projections.PIXEL_PER_LINE = 20.0heuristic.EnableMouseInputconfig flag, default off — pointer events are dropped on the floor unless enabled.Main menu support
Themed cursor
scripts/gen_cursors.pyrebuilds both variants from the source asset, auto-detects the hotspot, and syncs them intotarget/<profile>/assetsso tweaks don't need a cargo rebuild.HideMouseCursorpreference.Reusable helpers (used by the main menu, ready for other screens)
menu_list::item_rects— hit rect math for vertical menus, next to the actor builder.components::shared::menu_pointer::MenuPointer— hover/click bookkeeping for list-style screens.components::shared::hitbox::{HitRect, hit_test}— geometry primitives.