Browse Source

Refactored UiList ViewPort Logic

pull/3594/head
obligaron 4 years ago committed by Anders Jenbo
parent
commit
adfdb1e54f
  1. 62
      Source/DiabloUI/diabloui.cpp
  2. 3
      Source/DiabloUI/diabloui.h
  3. 51
      Source/DiabloUI/selhero.cpp

62
Source/DiabloUI/diabloui.cpp

@ -44,7 +44,7 @@ namespace devilution {
std::size_t SelectedItemMax;
std::size_t ListViewportSize = 1;
const std::size_t *ListOffset = nullptr;
std::size_t listOffset = 0;
std::array<Art, 3> ArtLogos;
std::array<Art, 3> ArtFocus;
@ -84,13 +84,21 @@ struct ScrollBarState {
}
} scrollBarState;
void AdjustListOffset(std::size_t itemIndex)
{
if (itemIndex >= listOffset + ListViewportSize)
listOffset = itemIndex - (ListViewportSize - 1);
if (itemIndex < listOffset)
listOffset = itemIndex;
}
} // namespace
void UiInitList(int count, void (*fnFocus)(int value), void (*fnSelect)(int value), void (*fnEsc)(), const std::vector<std::unique_ptr<UiItemBase>> &items, bool itemsWraps, bool (*fnYesNo)(), size_t selectedItem /*= 0*/)
void UiInitList(size_t listViewportSize, void (*fnFocus)(int value), void (*fnSelect)(int value), void (*fnEsc)(), const std::vector<std::unique_ptr<UiItemBase>> &items, bool itemsWraps, bool (*fnYesNo)(), size_t selectedItem /*= 0*/)
{
SelectedItem = selectedItem;
SelectedItemMax = std::max(count - 1, 0);
ListViewportSize = count;
SelectedItemMax = 0;
ListViewportSize = listViewportSize;
gfnListFocus = fnFocus;
gfnListSelect = fnSelect;
gfnListEsc = fnEsc;
@ -99,7 +107,8 @@ void UiInitList(int count, void (*fnFocus)(int value), void (*fnSelect)(int valu
for (const auto &item : items)
gUiItems.push_back(item.get());
UiItemsWraps = itemsWraps;
ListOffset = nullptr;
listOffset = 0;
AdjustListOffset(selectedItem);
if (fnFocus != nullptr)
fnFocus(selectedItem);
@ -107,6 +116,7 @@ void UiInitList(int count, void (*fnFocus)(int value), void (*fnSelect)(int valu
SDL_StopTextInput(); // input is enabled by default
#endif
textInputActive = false;
UiScrollbar *uiScrollbar = nullptr;
for (const auto &item : items) {
if (item->m_type == UiType::Edit) {
auto *pItemUIEdit = static_cast<UiEdit *>(item.get());
@ -124,18 +134,20 @@ void UiInitList(int count, void (*fnFocus)(int value), void (*fnSelect)(int valu
#endif
UiTextInput = pItemUIEdit->m_value;
UiTextInputLen = pItemUIEdit->m_max_length;
} else if (item->m_type == UiType::List) {
auto *uiList = static_cast<UiList *>(item.get());
SelectedItemMax = std::max(uiList->m_vecItems.size() - 1, static_cast<size_t>(0));
} else if (item->m_type == UiType::Scrollbar) {
uiScrollbar = static_cast<UiScrollbar *>(item.get());
}
}
}
void UiInitScrollBar(UiScrollbar *uiSb, std::size_t viewportSize, const std::size_t *currentOffset)
{
ListViewportSize = viewportSize;
ListOffset = currentOffset;
if (ListViewportSize >= static_cast<std::size_t>(SelectedItemMax + 1)) {
uiSb->add_flag(UiFlags::ElementHidden);
} else {
uiSb->remove_flag(UiFlags::ElementHidden);
if (uiScrollbar != nullptr) {
if (ListViewportSize >= static_cast<std::size_t>(SelectedItemMax + 1)) {
uiScrollbar->add_flag(UiFlags::ElementHidden);
} else {
uiScrollbar->remove_flag(UiFlags::ElementHidden);
}
}
}
@ -175,6 +187,8 @@ void UiFocus(std::size_t itemIndex)
UiPlayMoveSound();
AdjustListOffset(itemIndex);
if (gfnListFocus != nullptr)
gfnListFocus(itemIndex);
}
@ -199,33 +213,33 @@ void UiFocusDown()
void UiFocusPageUp()
{
if (ListOffset == nullptr || *ListOffset == 0) {
if (listOffset == 0) {
UiFocus(0);
} else {
const std::size_t relpos = SelectedItem - *ListOffset;
const std::size_t relpos = SelectedItem - listOffset;
std::size_t prevPageStart = SelectedItem - relpos;
if (prevPageStart >= ListViewportSize)
prevPageStart -= ListViewportSize;
else
prevPageStart = 0;
UiFocus(prevPageStart);
UiFocus(*ListOffset + relpos);
UiFocus(listOffset + relpos);
}
}
void UiFocusPageDown()
{
if (ListOffset == nullptr || *ListOffset + ListViewportSize > static_cast<std::size_t>(SelectedItemMax)) {
if (listOffset + ListViewportSize > static_cast<std::size_t>(SelectedItemMax)) {
UiFocus(SelectedItemMax);
} else {
const std::size_t relpos = SelectedItem - *ListOffset;
const std::size_t relpos = SelectedItem - listOffset;
std::size_t nextPageEnd = SelectedItem + (ListViewportSize - relpos - 1);
if (nextPageEnd + ListViewportSize <= static_cast<std::size_t>(SelectedItemMax))
nextPageEnd += ListViewportSize;
else
nextPageEnd = SelectedItemMax;
UiFocus(nextPageEnd);
UiFocus(*ListOffset + relpos);
UiFocus(listOffset + relpos);
}
}
@ -753,10 +767,10 @@ void Render(const UiList *uiList)
{
const Surface &out = Surface(DiabloUiSurface());
for (std::size_t i = 0; i < uiList->m_vecItems.size(); ++i) {
SDL_Rect rect = uiList->itemRect(i);
for (std::size_t i = listOffset; i < uiList->m_vecItems.size() && (i - listOffset) < ListViewportSize; ++i) {
SDL_Rect rect = uiList->itemRect(i - listOffset);
const UiListItem *item = uiList->GetItem(i);
if (i + (ListOffset == nullptr ? 0 : *ListOffset) == SelectedItem)
if (i == SelectedItem)
DrawSelector(rect);
Rectangle rectangle { { rect.x, rect.y }, { rect.w, rect.h } };
@ -856,7 +870,7 @@ bool HandleMouseEventList(const SDL_Event &event, UiList *uiList)
return false;
std::size_t index = uiList->indexAt(event.button.y);
index += (ListOffset == nullptr ? 0 : *ListOffset);
index += listOffset;
if (gfnListFocus != nullptr && SelectedItem != index) {
UiFocus(index);

3
Source/DiabloUI/diabloui.h

@ -122,8 +122,7 @@ void UiAddLogo(std::vector<std::unique_ptr<UiItemBase>> *vecDialog, int size = L
void UiFocusNavigationSelect();
void UiFocusNavigationEsc();
void UiFocusNavigationYesNo();
void UiInitList(int count, void (*fnFocus)(int value), void (*fnSelect)(int value), void (*fnEsc)(), const std::vector<std::unique_ptr<UiItemBase>> &items, bool wraps = false, bool (*fnYesNo)() = NULL, size_t selectedItem = 0);
void UiInitScrollBar(UiScrollbar *uiSb, std::size_t viewportSize, const std::size_t *currentOffset);
void UiInitList(size_t listViewportSize, void (*fnFocus)(int value), void (*fnSelect)(int value), void (*fnEsc)(), const std::vector<std::unique_ptr<UiItemBase>> &items, bool wraps = false, bool (*fnYesNo)() = NULL, size_t selectedItem = 0);
void UiClearScreen();
void UiPollAndRender();
void UiRenderItems(const std::vector<UiItemBase *> &items);

51
Source/DiabloUI/selhero.cpp

@ -88,33 +88,6 @@ void SelheroSetStats()
std::size_t listOffset = 0;
UiArtTextButton *SELLIST_DIALOG_DELETE_BUTTON;
void SelheroUpdateViewportItems()
{
const std::size_t numViewportHeroes = std::min(selhero_SaveCount - listOffset, MaxViewportItems);
for (std::size_t i = 0; i < numViewportHeroes; i++) {
const std::size_t index = i + listOffset;
vecSelHeroDlgItems[i]->m_text = selhero_heros[index].name;
vecSelHeroDlgItems[i]->m_value = static_cast<int>(index);
}
if (numViewportHeroes < MaxViewportItems) {
vecSelHeroDlgItems[numViewportHeroes]->m_text = _("New Hero");
vecSelHeroDlgItems[numViewportHeroes]->m_value = static_cast<int>(selhero_SaveCount);
}
}
void SelheroScrollIntoView(std::size_t index)
{
std::size_t newOffset = listOffset;
if (index >= listOffset + MaxViewportItems)
newOffset = index - (MaxViewportItems - 1);
if (index < listOffset)
newOffset = index;
if (newOffset != listOffset) {
listOffset = newOffset;
SelheroUpdateViewportItems();
}
}
bool SelHeroGetHeroInfo(_uiheroinfo *pInfo)
{
selhero_heros[selhero_SaveCount] = *pInfo;
@ -127,7 +100,6 @@ bool SelHeroGetHeroInfo(_uiheroinfo *pInfo)
void SelheroListFocus(int value)
{
const auto index = static_cast<std::size_t>(value);
SelheroScrollIntoView(index);
UiFlags baseFlags = UiFlags::AlignCenter | UiFlags::FontSize30;
if (selhero_SaveCount != 0 && index < selhero_SaveCount) {
memcpy(&selhero_heroInfo, &selhero_heros[index], sizeof(selhero_heroInfo));
@ -506,27 +478,17 @@ void selhero_List_Init()
vecSelDlgItems.push_back(std::make_unique<UiArtText>(_("Select Hero"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));
vecSelHeroDlgItems.clear();
const size_t numViewportHeroes = std::min(selhero_SaveCount + 1, MaxViewportItems);
for (std::size_t i = 0; i < numViewportHeroes; i++) {
vecSelHeroDlgItems.push_back(std::make_unique<UiListItem>("", -1));
}
// Adjust list to last selected hero
for (size_t i = 0; i < selhero_SaveCount; i++) {
if (selhero_heros[i].saveNumber == selhero_heroInfo.saveNumber) {
for (std::size_t i = 0; i < selhero_SaveCount; i++) {
vecSelHeroDlgItems.push_back(std::make_unique<UiListItem>(selhero_heros[i].name, static_cast<int>(i)));
if (selhero_heros[i].saveNumber == selhero_heroInfo.saveNumber)
selectedItem = i;
if (i > (MaxViewportItems - 1))
listOffset = i - (MaxViewportItems - 1);
break;
}
}
SelheroUpdateViewportItems();
vecSelHeroDlgItems.push_back(std::make_unique<UiListItem>(_("New Hero"), static_cast<int>(selhero_SaveCount)));
vecSelDlgItems.push_back(std::make_unique<UiList>(vecSelHeroDlgItems, PANEL_LEFT + 265, (UI_OFFSET_Y + 256), 320, 26, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorUiGold));
SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 585), (Sint16)(UI_OFFSET_Y + 244), 25, 178 };
auto pinnedScrollBar = std::make_unique<UiScrollbar>(&ArtScrollBarBackground, &ArtScrollBarThumb, &ArtScrollBarArrow, rect2);
auto *scrollBar = pinnedScrollBar.get();
vecSelDlgItems.push_back(std::move(pinnedScrollBar));
vecSelDlgItems.push_back(std::move(std::make_unique<UiScrollbar>(&ArtScrollBarBackground, &ArtScrollBarThumb, &ArtScrollBarArrow, rect2)));
SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 239), (Sint16)(UI_OFFSET_Y + 429), 120, 35 };
vecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_("OK"), &UiFocusNavigationSelect, rect3, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));
@ -539,8 +501,7 @@ void selhero_List_Init()
SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 489), (Sint16)(UI_OFFSET_Y + 429), 120, 35 };
vecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_("Cancel"), &UiFocusNavigationEsc, rect5, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));
UiInitList(selhero_SaveCount + 1, SelheroListFocus, SelheroListSelect, SelheroListEsc, vecSelDlgItems, false, SelheroListDeleteYesNo, selectedItem);
UiInitScrollBar(scrollBar, MaxViewportItems, &listOffset);
UiInitList(MaxViewportItems, SelheroListFocus, SelheroListSelect, SelheroListEsc, vecSelDlgItems, false, SelheroListDeleteYesNo, selectedItem);
if (selhero_isMultiPlayer) {
title = _("Multi Player Characters");
} else {

Loading…
Cancel
Save