From 4d8f715d509267b4284c59ce8d4f423f1dae9d7c Mon Sep 17 00:00:00 2001 From: Marcus Minhorst Date: Sun, 17 Aug 2025 16:26:07 -0400 Subject: [PATCH] Corrected overscroll behavior --- src/common/menu/optionmenu.cpp | 1 + .../zscript/engine/ui/menu/optionmenu.zs | 51 +++++++++++-------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/common/menu/optionmenu.cpp b/src/common/menu/optionmenu.cpp index 012dbf852..dcf052217 100644 --- a/src/common/menu/optionmenu.cpp +++ b/src/common/menu/optionmenu.cpp @@ -41,6 +41,7 @@ CVARD(Bool, silence_menu_scroll, true, CVAR_GLOBALCONFIG | CVAR_ARCHIVE, "Silences cursor movement when using mouse wheel"); CVARD(Bool, silence_menu_hover, true, CVAR_GLOBALCONFIG | CVAR_ARCHIVE, "Silences cursor movement when implicitly selecting with mouse"); +CVARD(Int, menu_overscroll, 8, CVAR_GLOBALCONFIG | CVAR_ARCHIVE, "Number of lines you can scroll past the bottom of a menu"); //============================================================================= // diff --git a/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs b/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs index e77b952c0..8da6cd7ca 100644 --- a/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs @@ -101,6 +101,11 @@ class OptionMenu : Menu int MaxItems; OptionMenuItem mFocusControl; + bool ScrollSound; + bool HoverSound; + int OverScroll; + int OverScrollThreshold; // >= 0 : how much smaller a menu can be than the page to overscroll + //============================================================================= // // @@ -116,6 +121,11 @@ class OptionMenu : Menu AnimatedTransition = desc.mAnimatedTransition; Animated = desc.mAnimated; + ScrollSound = ! Cvar.FindCVar("silence_menu_scroll").getInt(); + HoverSound = ! Cvar.FindCVar("silence_menu_hover").getInt(); + OverScroll = MAX(0, Cvar.FindCVar("menu_overscroll").getInt()); + OverScrollThreshold = OverScroll / 3; // this _could_ be exposed, but meh + let itemCount = mDesc.mItems.size(); if (itemCount > 0) { @@ -223,12 +233,11 @@ class OptionMenu : Menu override bool OnUIEvent(UIEvent ev) { - bool silentScroll = Cvar.FindCVar("silence_menu_scroll").getInt(); if (ev.type == UIEvent.Type_WheelUp) { if (MenuScrollViewport(-2, true) ) { - if (!silentScroll) MenuSound ("menu/cursor"); + if (ScrollSound) MenuSound ("menu/cursor"); } return true; } @@ -236,7 +245,7 @@ class OptionMenu : Menu { if (MenuScrollViewport(2, true)) { - if (!silentScroll) MenuSound ("menu/cursor"); + if (ScrollSound) MenuSound ("menu/cursor"); } return true; } @@ -342,7 +351,7 @@ class OptionMenu : Menu int maxItemsInternal = MaxItems; if (maxItemsInternal < RemainingVisibleItems(0)) { - maxItemsInternal -= 2; + maxItemsInternal -= OverScroll; } if (maxItemsInternal <= 0) maxItemsInternal = 1; @@ -353,9 +362,9 @@ class OptionMenu : Menu if (mDesc.mItems[i].Visible()) { visibleItemsOnPage++; - if (visibleItemsOnPage >= maxItemsInternal) + if (visibleItemsOnPage > maxItemsInternal) { - newTopIndex = i; + newTopIndex = i - 1; break; } } @@ -500,19 +509,13 @@ class OptionMenu : Menu mDesc.mScrollPos += lines; // backtrack if we overshot - int visible = RemainingVisibleItems(mDesc.mScrollPos); - if (visible < MaxItems) + int visible; + int MinItems = MaxItems - OverScroll; + while (mDesc.mScrollPos > 0) { - mDesc.mScrollPos = MAX(0, LastVisibleItem() - MaxItems); visible = RemainingVisibleItems(mDesc.mScrollPos); - while (visible < MaxItems && mDesc.mScrollPos > 0) - { - if (mDesc.mItems[mDesc.mScrollPos].Visible()) - { - visible++; - } - mDesc.mScrollPos--; - } + if (visible > MinItems) break; + mDesc.mScrollPos--; } // ensure cursor is visible (if possible) @@ -641,8 +644,7 @@ class OptionMenu : Menu { mDesc.mSelectedItem = i; - bool silentHover = Cvar.FindCVar("silence_menu_hover").getInt(); - if (!silentHover) MenuSound ("menu/cursor"); + if (HoverSound) MenuSound ("menu/cursor"); } mDesc.mItems[i].MouseEvent(type, x, y); return true; @@ -713,6 +715,8 @@ class OptionMenu : Menu //============================================================================= override void Drawer () { + int lastVisible; + bool drawCanScrollDown; int y = mDesc.mPosition; if (y <= 0) @@ -760,15 +764,18 @@ class OptionMenu : Menu y += fontheight; } - CanScrollUp = (mDesc.mScrollPos > 0); - CanScrollDown = LastVisibleItem() >= i; + lastVisible = LastVisibleItem(); + drawCanScrollDown = lastVisible >= i; + CanScrollUp = mDesc.mScrollPos > 0; + CanScrollDown = lastVisible + OverScroll >= i + && RemainingVisibleItems(0) > MaxItems-OverScrollThreshold; VisBottom = lastDrawnItemIndex; if (CanScrollUp) { DrawOptionText(screen.GetWidth() - 11 * CleanXfac_1, ytop, OptionMenuSettings.mFontColorSelection, "▲"); } - if (CanScrollDown) + if (drawCanScrollDown) { DrawOptionText(screen.GetWidth() - 11 * CleanXfac_1 , y - 8*CleanYfac_1, OptionMenuSettings.mFontColorSelection, "▼"); }