From 130275a7b2a0086534d890660c917cda5f181f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 3 Sep 2022 15:43:07 +0200 Subject: [PATCH 1/2] Refactor editor automapper config list using `CScrollRegion` - Fix the currently selected item not being highlighted after opening the dialog. - Remove static limit of 255 automapper rules, after which the editor previously caused out-of-bounds accesses, by using the address of the automapper config name as button ID. --- src/game/editor/popups.cpp | 74 ++++++++++---------------------------- 1 file changed, 18 insertions(+), 56 deletions(-) diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 5a3863cbf..900edfe1b 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -1472,70 +1472,34 @@ static int s_AutoMapConfigCurrent = -100; int CEditor::PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View, void *pContext) { CLayerTiles *pLayer = static_cast(pEditor->GetSelectedLayer(0)); - CUIRect Button; - static int s_aAutoMapperConfigButtons[256]; CAutoMapper *pAutoMapper = &pEditor->m_Map.m_vpImages[pLayer->m_Image]->m_AutoMapper; const float ButtonHeight = 12.0f; const float ButtonMargin = 2.0f; - static float s_ScrollValue = 0; + static CScrollRegion s_ScrollRegion; + vec2 ScrollOffset(0.0f, 0.0f); + CScrollRegionParams ScrollParams; + ScrollParams.m_ScrollbarWidth = 10.0f; + ScrollParams.m_ScrollbarMargin = 3.0f; + ScrollParams.m_ScrollUnit = (ButtonHeight + ButtonMargin) * 5; + s_ScrollRegion.Begin(&View, &ScrollOffset, &ScrollParams); + View.y += ScrollOffset.y; - // Add 1 more for the "None" option. - float ListHeight = (ButtonHeight + ButtonMargin) * (pAutoMapper->ConfigNamesNum() + 1); - float ScrollDifference = ListHeight - View.h; - - // Disable scrollbar if not needed. - if(ListHeight > View.h) + for(int i = -1; i < pAutoMapper->ConfigNamesNum(); i++) { - CUIRect Scroll; - View.VSplitRight(20.0f, &View, &Scroll); - s_ScrollValue = pEditor->UI()->DoScrollbarV(&s_ScrollValue, &Scroll, s_ScrollValue); - - if(pEditor->UI()->MouseInside(&View) || pEditor->UI()->MouseInside(&Scroll)) + CUIRect Button; + View.HSplitTop(ButtonMargin, nullptr, &View); + View.HSplitTop(ButtonHeight, &Button, &View); + if(s_ScrollRegion.AddRect(Button)) { - int ScrollNum = (int)((ListHeight / ButtonHeight) + 1); - if(ScrollNum > 0) - { - if(pEditor->Input()->KeyPress(KEY_MOUSE_WHEEL_UP)) - s_ScrollValue = clamp(s_ScrollValue - 1.0f / ScrollNum, 0.0f, 1.0f); - if(pEditor->Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN)) - s_ScrollValue = clamp(s_ScrollValue + 1.0f / ScrollNum, 0.0f, 1.0f); - } - } - - // Margin for scrollbar - View.VSplitRight(2.0f, &View, nullptr); - } - - float ListStartAt = ScrollDifference * s_ScrollValue; - - if(ListStartAt < 0.0f) - ListStartAt = 0.0f; - - float ListStopAt = ListHeight - ScrollDifference * (1 - s_ScrollValue); - float ListCur = 0; - - pEditor->UI()->ClipEnable(&View); - - for(int i = 0; i < pAutoMapper->ConfigNamesNum() + 1; i++) - { - if(ListCur > ListStopAt) - break; - - if(ListCur >= ListStartAt) - { - View.HSplitTop(ButtonMargin, nullptr, &View); - View.HSplitTop(ButtonHeight, &Button, &View); - if(pEditor->DoButton_MenuItem(&s_aAutoMapperConfigButtons[i], i == 0 ? "None" : pAutoMapper->GetConfigName(i - 1), i == s_AutoMapConfigCurrent, &Button, 0, nullptr)) - { + static int s_NoneButton = 0; + if(pEditor->DoButton_MenuItem(i == -1 ? (void *)&s_NoneButton : pAutoMapper->GetConfigName(i), i == -1 ? "None" : pAutoMapper->GetConfigName(i), i == s_AutoMapConfigCurrent, &Button, 0, nullptr)) s_AutoMapConfigSelected = i; - } } - ListCur += ButtonHeight + ButtonMargin; } - pEditor->UI()->ClipDisable(); + s_ScrollRegion.End(); return 0; } @@ -1546,9 +1510,7 @@ void CEditor::PopupSelectConfigAutoMapInvoke(int Current, float x, float y) s_AutoMapConfigSelected = -100; s_AutoMapConfigCurrent = Current; CLayerTiles *pLayer = static_cast(GetSelectedLayer(0)); - int ItemCount = m_Map.m_vpImages[pLayer->m_Image]->m_AutoMapper.ConfigNamesNum(); - if(ItemCount > 10) - ItemCount = 10; + const int ItemCount = minimum(m_Map.m_vpImages[pLayer->m_Image]->m_AutoMapper.ConfigNamesNum(), 10); // Width for buttons is 120, 15 is the scrollbar width, 2 is the margin between both. UiInvokePopupMenu(&s_AutoMapConfigSelectID, 0, x, y, 120.0f + 15.0f + 2.0f, 26.0f + 14.0f * ItemCount, PopupSelectConfigAutoMap); } @@ -1560,7 +1522,7 @@ int CEditor::PopupSelectConfigAutoMapResult() s_AutoMapConfigCurrent = s_AutoMapConfigSelected; s_AutoMapConfigSelected = -100; - return s_AutoMapConfigCurrent - 1; + return s_AutoMapConfigCurrent; } // DDRace From 977f1a8245c137314005f2f6c150b223d22c2e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 3 Sep 2022 17:13:26 +0200 Subject: [PATCH 2/2] Refactor editor server settings list using `CScrollRegion` --- src/game/editor/editor.cpp | 58 +++++++++++--------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 33693cadf..7af82e196 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -5422,60 +5422,34 @@ void CEditor::RenderServerSettingsEditor(CUIRect View, bool ShowServerSettingsEd CUIRect ListBox; View.Margin(1.0f, &ListBox); - float ListHeight = 17.0f * m_Map.m_vSettings.size(); - static float s_ScrollValue = 0; + const float ButtonHeight = 15.0f; + const float ButtonMargin = 2.0f; - float ScrollDifference = ListHeight - ListBox.h; + static CScrollRegion s_ScrollRegion; + vec2 ScrollOffset(0.0f, 0.0f); + CScrollRegionParams ScrollParams; + ScrollParams.m_ScrollUnit = (ButtonHeight + ButtonMargin) * 5.0f; + s_ScrollRegion.Begin(&ListBox, &ScrollOffset, &ScrollParams); + ListBox.y += ScrollOffset.y; - if(ListHeight > ListBox.h) // Do we even need a scrollbar? - { - CUIRect Scroll; - ListBox.VSplitRight(20.0f, &ListBox, &Scroll); - s_ScrollValue = UI()->DoScrollbarV(&s_ScrollValue, &Scroll, s_ScrollValue); - - if(UI()->MouseInside(&Scroll) || UI()->MouseInside(&ListBox)) - { - int ScrollNum = (int)((ListHeight - ListBox.h) / 17.0f) + 1; - if(ScrollNum > 0) - { - if(Input()->KeyPress(KEY_MOUSE_WHEEL_UP)) - s_ScrollValue = clamp(s_ScrollValue - 1.0f / ScrollNum, 0.0f, 1.0f); - if(Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN)) - s_ScrollValue = clamp(s_ScrollValue + 1.0f / ScrollNum, 0.0f, 1.0f); - } - } - } - - float ListStartAt = ScrollDifference * s_ScrollValue; - if(ListStartAt < 0.0f) - ListStartAt = 0.0f; - - float ListStopAt = ListHeight - ScrollDifference * (1 - s_ScrollValue); - float ListCur = 0; - - UI()->ClipEnable(&ListBox); for(size_t i = 0; i < m_Map.m_vSettings.size(); i++) { - if(ListCur > ListStopAt) - break; - - if(ListCur >= ListStartAt) + CUIRect Button; + ListBox.HSplitTop(ButtonHeight, &Button, &ListBox); + ListBox.HSplitTop(ButtonMargin, nullptr, &ListBox); + Button.VSplitLeft(5.0f, nullptr, &Button); + if(s_ScrollRegion.AddRect(Button)) { - CUIRect Button; - ListBox.HSplitTop(15.0f, &Button, &ListBox); - ListBox.HSplitTop(2.0f, nullptr, &ListBox); - Button.VSplitLeft(5.0f, nullptr, &Button); - if(DoButton_MenuItem(&m_Map.m_vSettings[i], m_Map.m_vSettings[i].m_aCommand, s_CommandSelectedIndex >= 0 && (size_t)s_CommandSelectedIndex == i, &Button, 0, nullptr)) { s_CommandSelectedIndex = i; - str_copy(m_aSettingsCommand, m_Map.m_vSettings[i].m_aCommand, sizeof(m_aSettingsCommand)); + str_copy(m_aSettingsCommand, m_Map.m_vSettings[i].m_aCommand); UI()->SetActiveItem(&m_CommandBox); } } - ListCur += 17.0f; } - UI()->ClipDisable(); + + s_ScrollRegion.End(); } int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View, void *pContext)