From 7086f463e50ed0d71583e47c22ba9ac98438bdb0 Mon Sep 17 00:00:00 2001 From: Marcus Minhorst Date: Fri, 5 Sep 2025 20:13:13 -0400 Subject: [PATCH] Keep cursor in screen when resizing --- src/common/menu/optionmenu.cpp | 2 +- .../zscript/engine/ui/menu/optionmenu.zs | 56 +++++++++++++------ 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/common/menu/optionmenu.cpp b/src/common/menu/optionmenu.cpp index dcf052217..2d82515a3 100644 --- a/src/common/menu/optionmenu.cpp +++ b/src/common/menu/optionmenu.cpp @@ -4,6 +4,7 @@ ** **--------------------------------------------------------------------------- ** Copyright 2010-2017 Christoph Oelckers +** Copyright 2017-2025 GZDoom Maintainers and Contributors ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -33,7 +34,6 @@ */ #include "c_cvars.h" -#include "v_video.h" #include "menu.h" #include "vm.h" diff --git a/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs b/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs index d56b1b786..368eb29d4 100644 --- a/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/optionmenu.zs @@ -121,6 +121,7 @@ class OptionMenu : Menu DontBlur = desc.mDontBlur; AnimatedTransition = desc.mAnimatedTransition; Animated = desc.mAnimated; + MaxItems = 1; ScrollSound = ! Cvar.FindCVar("silence_menu_scroll").getInt(); HoverSound = ! Cvar.FindCVar("silence_menu_hover").getInt(); @@ -170,7 +171,6 @@ class OptionMenu : Menu return NULL; } - //============================================================================= // // @@ -466,6 +466,36 @@ class OptionMenu : Menu return mDesc.mSelectedItem - startedAt; } + void ClampCursor() + { + int first = FirstSelectable(); + int last = LastSelectableItem(); + + mDesc.mSelectedItem = min(max(first, mDesc.mSelectedItem), last); + if (mDesc.mSelectedItem < 0) mDesc.mSelectedItem = 0; + + int firstSelectable = -1; + int lastSelectable = -1; + int visible = 0; + for (int i = mDesc.mScrollPos; visible < MaxItems && i <= last; i++) + { + if (!mDesc.mItems[i].Visible()) continue; + visible++; + if (!mDesc.mItems[i].Selectable()) continue; + lastSelectable = i; + if (firstSelectable == -1) firstSelectable = i; + } + + if (firstSelectable != -1 && mDesc.mSelectedItem < firstSelectable) + { + mDesc.mSelectedItem = firstSelectable; + } + else if (lastSelectable != -1 && mDesc.mSelectedItem > lastSelectable) + { + mDesc.mSelectedItem = lastSelectable; + } + } + //============================================================================= // // Moves the viewport by the specified number of lines @@ -495,25 +525,12 @@ class OptionMenu : Menu return 0; } - int lastItem = LastVisibleItem(); - mDesc.mScrollPos = min(max(0, mDesc.mScrollPos + lines), lastItem); + mDesc.mScrollPos = min(max(0, mDesc.mScrollPos + lines), LastVisibleItem()); if (lines < 0) // up { // ensure cursor is visible (if possible) - int lastSelectable = -1; - int visible = 0; - for (int i = mDesc.mScrollPos; visible < MaxItems && i <= lastItem; i++) - { - if (!mDesc.mItems[i].Visible()) continue; - visible++; - if (!mDesc.mItems[i].Selectable()) continue; - lastSelectable = i; - } - if (cursor && lastSelectable != -1 && mDesc.mSelectedItem > lastSelectable) - { - mDesc.mSelectedItem = lastSelectable; - } + if (cursor) ClampCursor(); } else if (lines > 0) // down { @@ -539,6 +556,7 @@ class OptionMenu : Menu mDesc.mSelectedItem = temp + i; break; } + ClampCursor(); } } @@ -741,7 +759,11 @@ class OptionMenu : Menu int ytop = y + mDesc.mScrollTop * 8 * CleanYfac_1; LastRow = screen.GetHeight() - OptionHeight() * CleanYfac_1; int rowheight = OptionMenuSettings.mLinespacing * CleanYfac_1 + 1; - MaxItems = (LastRow - y) / rowheight + 1; + + int _MaxItems = (LastRow - y) / rowheight + 1; + bool resized = _MaxItems != MaxItems; + MaxItems = _MaxItems; + if (resized) ClampCursor(); int i; int lastDrawnItemIndex = -1;