Scroll long menus and lists with the mouse wheel or a swipe

Touch clicks in menus happen on release without a swipe. The first-start
language picker is a flag grid that scrolls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-05 16:04:20 +01:00
1 parent d8e9184a9c
commit 6629472811
4 files changed
+157 -25

No files matched your search

+51 -6
View File
@@ -842,6 +842,8 @@ async fn main() {
let mut inp = Input { ldown: None, rdown: None, rlast: (0.0, 0.0), rdrag: false, mlast: None, minimap_drag: false, tlast: None, touch_world: false, inspect: None };
let mut touch = TouchInput::new();
let mut auto_touch = platform::coarse_pointer();
let mut menu_swipe: Option<(f32, f32)> = None; // a swipe over a menu: last finger y, unused distance
let mut menu_dragged = false; // the finger on a menu has swiped (no click when it lifts)
// until the mouse has really moved its position is (0, 0): no edge scrolling before that
let mut mouse_moved = false; // automatic mode: touch interface after a touch, desktop after a mouse click
let mut autosave_t = 0.0f32;
@@ -1025,11 +1027,45 @@ async fn main() {
}
}
let (_, wheel) = mouse_wheel();
if wheel != 0.0 && menu.page.is_some() {
let d = if wheel > 0.0 { -1 } else { 1 };
// an open language dropdown scrolls first
if !menu.lang_wheel(d) && menu.scrollable() {
menu.scroll_lines(d);
if wheel != 0.0 && ui.show_langsel {
ui.langsel_wheel(if wheel > 0.0 { -1 } else { 1 });
} else if wheel != 0.0 && menu.page.is_some() {
menu.wheel(if wheel > 0.0 { -1 } else { 1 });
} else if wheel != 0.0 {
ui.overview_wheel(ux, uy, if wheel > 0.0 { -1 } else { 1 });
}
// touch: a swipe over a menu, the language grid or the creature overview scrolls it,
// one line per row height
if touch_mode {
for g in &gestures {
match *g {
Gesture::Press(_) => menu_dragged = false,
Gesture::DragStart(p) if menu.page.is_some() || ui.show_langsel || ui.overview_wheel(p.x, p.y, 0) => {
menu_swipe = Some((p.y, 0.0));
menu_dragged = true;
}
Gesture::DragMove(p) => {
if let Some((last, acc)) = menu_swipe {
let mut acc = acc + p.y - last;
let step = ui::CH() * 2.0;
while acc.abs() >= step {
// finger up: the content follows it up, so the list scrolls down
let d = if acc < 0.0 { 1 } else { -1 };
if ui.show_langsel {
ui.langsel_wheel(d);
} else if menu.page.is_some() {
menu.wheel(d);
} else {
ui.overview_wheel(p.x, p.y, d);
}
acc += d as f32 * step;
}
menu_swipe = Some((p.y, acc));
}
}
Gesture::DragEnd | Gesture::Cancel => menu_swipe = None,
_ => {}
}
}
}
@@ -1269,7 +1305,16 @@ async fn main() {
}
// ---------------- left button (touch: a finger touching the interface)
let pressed = if touch_mode { gestures.iter().any(|g| matches!(g, Gesture::Press(_))) } else { is_mouse_button_pressed(MouseButton::Left) };
// (in menus and dialogs a touch clicks when the finger lifts without a swipe, so that
// swiping a list scrolls it instead of picking the entry under the finger)
let menu_touch = touch_mode && (in_menu || dialog);
let pressed = if menu_touch {
!menu_dragged && gestures.iter().any(|g| matches!(g, Gesture::Release(_)))
} else if touch_mode {
gestures.iter().any(|g| matches!(g, Gesture::Press(_)))
} else {
is_mouse_button_pressed(MouseButton::Left)
};
if touch_mode && pressed {
inp.touch_world = playing && !over_ui;
inp.inspect = None;