diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index af98c5daa..c69351a86 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1806,7 +1806,7 @@ void CMenus::RenderThemeSelection(CUIRect MainView) static CListBox s_ListBox; s_ListBox.DoHeader(&MainView, Localize("Theme"), 20.0f); - s_ListBox.DoStart(20.0f, vThemes.size(), 1, 3, SelectedTheme, nullptr, true); + s_ListBox.DoStart(20.0f, vThemes.size(), 1, 3, SelectedTheme); for(int i = 0; i < (int)vThemes.size(); i++) { diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 0fbe017fc..141255386 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -184,10 +184,9 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) g_Config.m_UiToolboxPage = (g_Config.m_UiToolboxPage + 3 + Direction) % 3; } - bool ListBoxUsed = !UI()->IsPopupOpen(); - static CListBox s_ListBox; - s_ListBox.DoStart(ms_ListheaderHeight, NumServers, 1, 3, -1, &View, false, &ListBoxUsed); + s_ListBox.SetActive(!UI()->IsPopupOpen()); + s_ListBox.DoStart(ms_ListheaderHeight, NumServers, 1, 3, -1, &View, false); int NumPlayers = 0; static int s_PrevSelectedIndex = -1; @@ -224,7 +223,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) pItem->m_pUIElement = UI()->GetNewUIElement(UIRectCount); } - const CListboxItem ListItem = s_ListBox.DoNextItem(pItem, str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0, &ListBoxUsed); + const CListboxItem ListItem = s_ListBox.DoNextItem(pItem, str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0); if(ListItem.m_Selected) m_SelectedIndex = i; @@ -984,11 +983,9 @@ CUI::EPopupMenuFunctionResult CMenus::PopupCountrySelection(void *pContext, CUIR SPopupCountrySelectionContext *pPopupContext = static_cast(pContext); CMenus *pMenus = pPopupContext->m_pMenus; - bool ListBoxUsed = Active; - static CListBox s_ListBox; - int OldSelected = -1; - s_ListBox.DoStart(50.0f, pMenus->m_pClient->m_CountryFlags.Num(), 8, 1, OldSelected, &View, false, &ListBoxUsed); + s_ListBox.SetActive(Active); + s_ListBox.DoStart(50.0f, pMenus->m_pClient->m_CountryFlags.Num(), 8, 1, -1, &View, false); if(pPopupContext->m_New) { @@ -999,10 +996,8 @@ CUI::EPopupMenuFunctionResult CMenus::PopupCountrySelection(void *pContext, CUIR for(size_t i = 0; i < pMenus->m_pClient->m_CountryFlags.Num(); ++i) { const CCountryFlags::CCountryFlag *pEntry = pMenus->m_pClient->m_CountryFlags.GetByIndex(i); - if(pEntry->m_CountryCode == pPopupContext->m_Selection) - OldSelected = i; - const CListboxItem Item = s_ListBox.DoNextItem(pEntry, OldSelected >= 0 && (size_t)OldSelected == i, &ListBoxUsed); + const CListboxItem Item = s_ListBox.DoNextItem(pEntry, pEntry->m_CountryCode == pPopupContext->m_Selection); if(!Item.m_Visible) continue; @@ -1020,7 +1015,7 @@ CUI::EPopupMenuFunctionResult CMenus::PopupCountrySelection(void *pContext, CUIR } const int NewSelected = s_ListBox.DoEnd(); - pPopupContext->m_Selection = pMenus->m_pClient->m_CountryFlags.GetByIndex(NewSelected)->m_CountryCode; + pPopupContext->m_Selection = NewSelected >= 0 ? pMenus->m_pClient->m_CountryFlags.GetByIndex(NewSelected)->m_CountryCode : -1; if(s_ListBox.WasItemSelected() || s_ListBox.WasItemActivated()) { g_Config.m_BrFilterCountry = 1; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index d8cdd17b7..ad22de6ca 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -363,15 +363,13 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) m_Dummy ^= 1; } - static bool s_ListBoxUsed = false; - if(UI()->CheckActiveItem(pClan) || UI()->CheckActiveItem(pName)) - s_ListBoxUsed = false; - // country flag selector MainView.HSplitTop(20.0f, 0, &MainView); int OldSelected = -1; static CListBox s_ListBox; - s_ListBox.DoStart(50.0f, m_pClient->m_CountryFlags.Num(), 10, 3, OldSelected, &MainView, true, &s_ListBoxUsed); + if(UI()->CheckActiveItem(&s_ClanInput) || UI()->CheckActiveItem(&s_NameInput)) + s_ListBox.SetActive(false); + s_ListBox.DoStart(50.0f, m_pClient->m_CountryFlags.Num(), 10, 3, OldSelected, &MainView); for(size_t i = 0; i < m_pClient->m_CountryFlags.Num(); ++i) { @@ -379,7 +377,7 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) if(pEntry->m_CountryCode == *pCountry) OldSelected = i; - const CListboxItem Item = s_ListBox.DoNextItem(&pEntry->m_CountryCode, OldSelected >= 0 && (size_t)OldSelected == i, &s_ListBoxUsed); + const CListboxItem Item = s_ListBox.DoNextItem(&pEntry->m_CountryCode, OldSelected >= 0 && (size_t)OldSelected == i); if(!Item.m_Visible) continue; @@ -1565,15 +1563,16 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) static const float sc_RowHeightResList = 22.0f; static const float sc_FontSizeResListHeader = 12.0f; static const float sc_FontSizeResList = 10.0f; - bool ListBoxUsed = !UI()->IsPopupOpen(); - int OldSelected = -1; + { int G = std::gcd(g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight); str_format(aBuf, sizeof(aBuf), "%s: %dx%d @%dhz %d bit (%d:%d)", Localize("Current"), (int)(g_Config.m_GfxScreenWidth * Graphics()->ScreenHiDPIScale()), (int)(g_Config.m_GfxScreenHeight * Graphics()->ScreenHiDPIScale()), g_Config.m_GfxScreenRefreshRate, g_Config.m_GfxColorDepth, g_Config.m_GfxScreenWidth / G, g_Config.m_GfxScreenHeight / G); + UI()->DoLabel(&ModeLabel, aBuf, sc_FontSizeResListHeader, TEXTALIGN_MC); } - UI()->DoLabel(&ModeLabel, aBuf, sc_FontSizeResListHeader, TEXTALIGN_MC); - s_ListBox.DoStart(sc_RowHeightResList, s_NumNodes, 1, 3, OldSelected, &ModeList, true, &ListBoxUsed); + int OldSelected = -1; + s_ListBox.SetActive(!UI()->IsPopupOpen()); + s_ListBox.DoStart(sc_RowHeightResList, s_NumNodes, 1, 3, OldSelected, &ModeList); for(int i = 0; i < s_NumNodes; ++i) { @@ -1586,7 +1585,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) OldSelected = i; } - const CListboxItem Item = s_ListBox.DoNextItem(&s_aModes[i], OldSelected == i, &ListBoxUsed); + const CListboxItem Item = s_ListBox.DoNextItem(&s_aModes[i], OldSelected == i); if(!Item.m_Visible) continue; @@ -2059,7 +2058,7 @@ bool CMenus::RenderLanguageSelection(CUIRect MainView) const int OldSelected = s_SelectedLanguage; - s_ListBox.DoStart(24.0f, g_Localization.Languages().size(), 1, 3, s_SelectedLanguage, &MainView, true); + s_ListBox.DoStart(24.0f, g_Localization.Languages().size(), 1, 3, s_SelectedLanguage, &MainView); for(const auto &Language : g_Localization.Languages()) { diff --git a/src/game/client/ui_listbox.cpp b/src/game/client/ui_listbox.cpp index f21728349..b73611809 100644 --- a/src/game/client/ui_listbox.cpp +++ b/src/game/client/ui_listbox.cpp @@ -18,6 +18,7 @@ CListBox::CListBox() m_HasHeader = false; m_AutoSpacing = 0.0f; m_ScrollbarIsShown = false; + m_Active = true; } void CListBox::DoBegin(const CUIRect *pRect) @@ -59,7 +60,7 @@ void CListBox::DoFooter(const char *pBottomText, float FooterHeight) m_FooterHeight = FooterHeight; } -void CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsPerScroll, int SelectedIndex, const CUIRect *pRect, bool Background, bool *pActive, int BackgroundCorners) +void CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsPerScroll, int SelectedIndex, const CUIRect *pRect, bool Background, int BackgroundCorners) { CUIRect View; if(pRect) @@ -96,7 +97,7 @@ void CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsP m_ListBoxItemSelected = false; // handle input - if(!pActive || *pActive) + if(m_Active) { if(UI()->ConsumeHotkey(CUI::HOTKEY_DOWN)) m_ListBoxNewSelOffset += 1; @@ -115,7 +116,7 @@ void CListBox::DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsP // setup the scrollbar m_ScrollOffset = vec2(0.0f, 0.0f); CScrollRegionParams ScrollParams; - ScrollParams.m_Active = !pActive || *pActive; + ScrollParams.m_Active = m_Active; ScrollParams.m_ScrollbarWidth = ScrollbarWidthMax(); ScrollParams.m_ScrollUnit = (m_ListBoxRowHeight + m_AutoSpacing) * RowsPerScroll; m_ScrollRegion.Begin(&m_ListBoxView, &m_ScrollOffset, &ScrollParams); @@ -144,7 +145,7 @@ CListboxItem CListBox::DoNextRow() return Item; } -CListboxItem CListBox::DoNextItem(const void *pId, bool Selected, bool *pActive) +CListboxItem CListBox::DoNextItem(const void *pId, bool Selected) { if(m_AutoSpacing > 0.0f && m_ListBoxItemIndex > 0) DoSpacing(m_AutoSpacing); @@ -165,18 +166,15 @@ CListboxItem CListBox::DoNextItem(const void *pId, bool Selected, bool *pActive) ItemClicked = true; m_ListBoxNewSelected = ThisItemIndex; m_ListBoxItemSelected = true; - if(pActive) - *pActive = true; + m_Active = true; } else ItemClicked = false; - const bool ProcessInput = !pActive || *pActive; - // process input, regard selected index if(m_ListBoxSelectedIndex == ThisItemIndex) { - if(ProcessInput && !m_ListBoxDoneEvents) + if(m_Active && !m_ListBoxDoneEvents) { m_ListBoxDoneEvents = true; @@ -187,7 +185,7 @@ CListboxItem CListBox::DoNextItem(const void *pId, bool Selected, bool *pActive) } } - Item.m_Rect.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, ProcessInput ? 0.5f : 0.33f), IGraphics::CORNER_ALL, 5.0f); + Item.m_Rect.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, m_Active ? 0.5f : 0.33f), IGraphics::CORNER_ALL, 5.0f); } if(UI()->HotItem() == pId && !m_ScrollRegion.IsAnimating()) { @@ -207,6 +205,8 @@ CListboxItem CListBox::DoSubheader() int CListBox::DoEnd() { m_ScrollRegion.End(); + m_Active |= m_ScrollRegion.Params().m_Active; + m_ScrollbarIsShown = m_ScrollRegion.IsScrollbarShown(); if(m_ListBoxNewSelOffset != 0 && m_ListBoxNumItems > 0 && m_ListBoxSelectedIndex == m_ListBoxNewSelected) { diff --git a/src/game/client/ui_listbox.h b/src/game/client/ui_listbox.h index 176877cec..fff29f26a 100644 --- a/src/game/client/ui_listbox.h +++ b/src/game/client/ui_listbox.h @@ -38,6 +38,7 @@ private: float m_FilterOffset; int m_BackgroundCorners; bool m_HasHeader; + bool m_Active; protected: CListboxItem DoNextRow(); @@ -50,14 +51,19 @@ public: void DoAutoSpacing(float Spacing = 20.0f) { m_AutoSpacing = Spacing; } void DoSpacing(float Spacing = 20.0f); void DoFooter(const char *pBottomText, float FooterHeight = 20.0f); // call before DoStart to create a footer - void DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsPerScroll, int SelectedIndex, const CUIRect *pRect = nullptr, bool Background = true, bool *pActive = nullptr, int BackgroundCorners = IGraphics::CORNER_ALL); + void DoStart(float RowHeight, int NumItems, int ItemsPerRow, int RowsPerScroll, int SelectedIndex, const CUIRect *pRect = nullptr, bool Background = true, int BackgroundCorners = IGraphics::CORNER_ALL); void ScrollToSelected() { m_ListBoxUpdateScroll = true; } - CListboxItem DoNextItem(const void *pID, bool Selected = false, bool *pActive = nullptr); + CListboxItem DoNextItem(const void *pID, bool Selected = false); CListboxItem DoSubheader(); int DoEnd(); - bool FilterMatches(const char *pNeedle) const; + + // Active state must be set before calling DoStart. + bool Active() const { return m_Active; } + void SetActive(bool Active) { m_Active = Active; } + bool WasItemSelected() const { return m_ListBoxItemSelected; } bool WasItemActivated() const { return m_ListBoxItemActivated; } + bool ScrollbarIsShown() const { return m_ScrollbarIsShown; } float ScrollbarWidth() const { return ScrollbarIsShown() ? ScrollbarWidthMax() : 0.0f; } float ScrollbarWidthMax() const { return 20.0f; } diff --git a/src/game/client/ui_scrollregion.cpp b/src/game/client/ui_scrollregion.cpp index c02447df9..12e9598bf 100644 --- a/src/game/client/ui_scrollregion.cpp +++ b/src/game/client/ui_scrollregion.cpp @@ -157,6 +157,7 @@ void CScrollRegion::End() m_SliderGrabPos.y = UI()->MouseY() - Slider.y; m_AnimTargetScrollY = m_ScrollY; m_AnimTime = 0.0f; + m_Params.m_Active = true; } } else if(InsideRail && UI()->MouseButtonClicked(0)) @@ -167,6 +168,7 @@ void CScrollRegion::End() m_SliderGrabPos.y = Slider.h / 2.0f; m_AnimTargetScrollY = m_ScrollY; m_AnimTime = 0.0f; + m_Params.m_Active = true; } else if(UI()->CheckActiveItem(pID) && !UI()->MouseButton(0)) { diff --git a/src/game/client/ui_scrollregion.h b/src/game/client/ui_scrollregion.h index b117f9c47..679c30720 100644 --- a/src/game/client/ui_scrollregion.h +++ b/src/game/client/ui_scrollregion.h @@ -134,6 +134,7 @@ public: bool IsRectClipped(const CUIRect &Rect) const; bool IsScrollbarShown() const; bool IsAnimating() const; + const CScrollRegionParams &Params() const { return m_Params; } }; #endif diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 432796497..39365a72b 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -4664,8 +4664,7 @@ void CEditor::RenderFileDialog() // filebox static CListBox s_ListBox; - static bool s_ListBoxUsed = false; - s_ListBoxUsed = !UI()->IsPopupOpen(); + s_ListBox.SetActive(!UI()->IsPopupOpen()); if(m_FileDialogStorageType == IStorage::TYPE_SAVE) { @@ -4791,11 +4790,11 @@ void CEditor::RenderFileDialog() } } - s_ListBox.DoStart(15.0f, m_vpFilteredFileList.size(), 1, 5, m_FilesSelectedIndex, &View, false, &s_ListBoxUsed); + s_ListBox.DoStart(15.0f, m_vpFilteredFileList.size(), 1, 5, m_FilesSelectedIndex, &View, false); for(size_t i = 0; i < m_vpFilteredFileList.size(); i++) { - const CListboxItem Item = s_ListBox.DoNextItem(m_vpFilteredFileList[i], m_FilesSelectedIndex >= 0 && (size_t)m_FilesSelectedIndex == i, &s_ListBoxUsed); + const CListboxItem Item = s_ListBox.DoNextItem(m_vpFilteredFileList[i], m_FilesSelectedIndex >= 0 && (size_t)m_FilesSelectedIndex == i); if(!Item.m_Visible) continue; @@ -4920,12 +4919,12 @@ void CEditor::RenderFileDialog() ButtonBar.VSplitRight(ButtonSpacing, &ButtonBar, nullptr); ButtonBar.VSplitRight(50.0f, &ButtonBar, &Button); - if(DoButton_Editor(&s_CancelButton, "Cancel", 0, &Button, 0, nullptr) || (s_ListBoxUsed && UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))) + if(DoButton_Editor(&s_CancelButton, "Cancel", 0, &Button, 0, nullptr) || (s_ListBox.Active() && UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))) m_Dialog = DIALOG_NONE; ButtonBar.VSplitRight(ButtonSpacing, &ButtonBar, nullptr); ButtonBar.VSplitRight(50.0f, &ButtonBar, &Button); - if(DoButton_Editor(&s_RefreshButton, "Refresh", 0, &Button, 0, nullptr) || (s_ListBoxUsed && (Input()->KeyIsPressed(KEY_F5) || (Input()->ModifierIsPressed() && Input()->KeyIsPressed(KEY_R))))) + if(DoButton_Editor(&s_RefreshButton, "Refresh", 0, &Button, 0, nullptr) || (s_ListBox.Active() && (Input()->KeyIsPressed(KEY_F5) || (Input()->ModifierIsPressed() && Input()->KeyIsPressed(KEY_R))))) FilelistPopulate(m_FileDialogLastPopulatedStorageType, true); ButtonBar.VSplitRight(ButtonSpacing, &ButtonBar, nullptr); @@ -4943,7 +4942,7 @@ void CEditor::RenderFileDialog() static CUI::SConfirmPopupContext s_ConfirmDeletePopupContext; if(m_FilesSelectedIndex >= 0 && m_vpFilteredFileList[m_FilesSelectedIndex]->m_StorageType == IStorage::TYPE_SAVE && !m_vpFilteredFileList[m_FilesSelectedIndex]->m_IsLink && str_comp(m_vpFilteredFileList[m_FilesSelectedIndex]->m_aFilename, "..") != 0) { - if(DoButton_Editor(&s_DeleteButton, "Delete", 0, &Button, 0, nullptr) || (s_ListBoxUsed && UI()->ConsumeHotkey(CUI::HOTKEY_DELETE))) + if(DoButton_Editor(&s_DeleteButton, "Delete", 0, &Button, 0, nullptr) || (s_ListBox.Active() && UI()->ConsumeHotkey(CUI::HOTKEY_DELETE))) { s_ConfirmDeletePopupContext.Reset(); s_ConfirmDeletePopupContext.YesNoButtons();