2 changed files with 196 additions and 196 deletions
@ -1,187 +1,187 @@
|
||||
#include "selstart.h" |
||||
|
||||
#include "DiabloUI/diabloui.h" |
||||
#include "DiabloUI/scrollbar.h" |
||||
#include "control.h" |
||||
#include "engine/render/text_render.hpp" |
||||
#include "hwcursor.hpp" |
||||
#include "options.h" |
||||
#include "utils/language.h" |
||||
|
||||
namespace devilution { |
||||
namespace { |
||||
|
||||
bool endMenu = false; |
||||
bool recreateUI = false; |
||||
|
||||
std::vector<std::unique_ptr<UiListItem>> vecDialogItems; |
||||
std::vector<std::unique_ptr<UiItemBase>> vecDialog; |
||||
std::vector<OptionEntryBase *> vecOptions; |
||||
|
||||
char optionDescription[256]; |
||||
|
||||
Rectangle rectDescription; |
||||
|
||||
enum class SpecialMenuEntry { |
||||
None = -1, |
||||
PreviousMenu = -2, |
||||
SwitchGame = -3, |
||||
ToggleSpawn = -4, |
||||
}; |
||||
|
||||
bool IsValidEntry(OptionEntryBase *pOptionEntry) |
||||
{ |
||||
return HasNoneOf(pOptionEntry->GetFlags(), OptionEntryFlags::Invisible | (gbIsHellfire ? OptionEntryFlags::OnlyDiablo : OptionEntryFlags::OnlyHellfire)); |
||||
} |
||||
|
||||
std::vector<DrawStringFormatArg> CreateDrawStringFormatArgForEntry(OptionEntryBase *pEntry) |
||||
{ |
||||
return std::vector<DrawStringFormatArg> { |
||||
{ pEntry->GetName().data(), UiFlags::ColorUiGold }, |
||||
{ pEntry->GetValueDescription().data(), UiFlags::ColorUiSilver } |
||||
}; |
||||
} |
||||
|
||||
void ItemFocused(int value) |
||||
{ |
||||
auto &vecItem = vecDialogItems[value]; |
||||
optionDescription[0] = '\0'; |
||||
if (vecItem->m_value < 0) { |
||||
return; |
||||
} |
||||
auto *pOption = vecOptions[vecItem->m_value]; |
||||
auto paragraphs = WordWrapString(pOption->GetDescription(), rectDescription.size.width, GameFont12, 1); |
||||
strncpy(optionDescription, paragraphs.c_str(), sizeof(optionDescription)); |
||||
} |
||||
|
||||
void ItemSelected(int value) |
||||
{ |
||||
auto &vecItem = vecDialogItems[value]; |
||||
if (vecItem->m_value < 0) { |
||||
auto specialMenuEntry = static_cast<SpecialMenuEntry>(vecItem->m_value); |
||||
switch (specialMenuEntry) { |
||||
case SpecialMenuEntry::None: |
||||
break; |
||||
case SpecialMenuEntry::PreviousMenu: |
||||
endMenu = true; |
||||
break; |
||||
case SpecialMenuEntry::SwitchGame: |
||||
gbIsHellfire = !gbIsHellfire; |
||||
endMenu = true; |
||||
recreateUI = true; |
||||
break; |
||||
case SpecialMenuEntry::ToggleSpawn: |
||||
gbIsSpawn = !gbIsSpawn; |
||||
UiSetSpawned(gbIsSpawn); |
||||
endMenu = true; |
||||
recreateUI = true; |
||||
break; |
||||
} |
||||
return; |
||||
} |
||||
|
||||
auto *pOption = vecOptions[vecItem->m_value]; |
||||
switch (pOption->GetType()) { |
||||
case OptionEntryType::Boolean: { |
||||
auto *pOptionBoolean = static_cast<OptionEntryBoolean *>(pOption); |
||||
pOptionBoolean->SetValue(!**pOptionBoolean); |
||||
} break; |
||||
case OptionEntryType::List: { |
||||
auto *pOptionList = static_cast<OptionEntryListBase *>(pOption); |
||||
size_t nextIndex = pOptionList->GetActiveListIndex() + 1; |
||||
if (nextIndex >= pOptionList->GetListSize()) |
||||
nextIndex = 0; |
||||
pOptionList->SetActiveListIndex(nextIndex); |
||||
} break; |
||||
} |
||||
vecDialogItems[value]->args.clear(); |
||||
for (auto &arg : CreateDrawStringFormatArgForEntry(pOption)) |
||||
vecDialogItems[value]->args.push_back(arg); |
||||
} |
||||
|
||||
void EscPressed() |
||||
{ |
||||
endMenu = true; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
void UiSettingsMenu() |
||||
{ |
||||
endMenu = false; |
||||
|
||||
do { |
||||
LoadBackgroundArt("ui_art\\black.pcx"); |
||||
LoadScrollBar(); |
||||
UiAddBackground(&vecDialog); |
||||
UiAddLogo(&vecDialog); |
||||
|
||||
Rectangle rectList = { { PANEL_LEFT + 50, (UI_OFFSET_Y + 204) }, { 540, 208 } }; |
||||
rectDescription = { { PANEL_LEFT + 24, rectList.position.y + rectList.size.height + 20 }, { 590, 35 } }; |
||||
|
||||
optionDescription[0] = '\0'; |
||||
|
||||
const char *titleText = _("Settings"); |
||||
vecDialog.push_back(std::make_unique<UiArtText>(titleText, MakeSdlRect(PANEL_LEFT, UI_OFFSET_Y + 161, PANEL_WIDTH, 35), UiFlags::FontSize30 | UiFlags::ColorUiSilver | UiFlags::AlignCenter, 8)); |
||||
vecDialog.push_back(std::make_unique<UiScrollbar>(&ArtScrollBarBackground, &ArtScrollBarThumb, &ArtScrollBarArrow, MakeSdlRect(rectList.position.x + rectList.size.width + 5, rectList.position.y, 25, rectList.size.height))); |
||||
vecDialog.push_back(std::make_unique<UiArtText>(optionDescription, MakeSdlRect(rectDescription), UiFlags::FontSize12 | UiFlags::ColorUiSilverDark | UiFlags::AlignCenter, 1)); |
||||
|
||||
if (diabdat_mpq && hellfire_mpq) |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>(gbIsHellfire ? _("Switch to Diablo") : _("Switch to Hellfire"), static_cast<int>(SpecialMenuEntry::SwitchGame), UiFlags::ColorUiGold)); |
||||
if (diabdat_mpq) |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>(gbIsSpawn ? _("Switch to Fullgame") : _("Switch to Shareware"), static_cast<int>(SpecialMenuEntry::ToggleSpawn), UiFlags::ColorUiGold)); |
||||
|
||||
bool switchOptionExists = vecDialogItems.size() > 0; |
||||
int catCount = switchOptionExists ? 1 : 0; |
||||
for (auto *pCategory : sgOptions.GetCategories()) { |
||||
bool categoryCreated = false; |
||||
for (auto *pEntry : pCategory->GetEntries()) { |
||||
if (!IsValidEntry(pEntry)) |
||||
continue; |
||||
if (!categoryCreated) { |
||||
if (catCount > 0) |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>("", -1, UiFlags::ElementDisabled)); |
||||
catCount += 1; |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>(pCategory->GetName().data(), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorWhitegold | UiFlags::ElementDisabled)); |
||||
categoryCreated = true; |
||||
} |
||||
auto formatArgs = CreateDrawStringFormatArgForEntry(pEntry); |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>("{}: {}", formatArgs, vecOptions.size(), UiFlags::ColorUiGold)); |
||||
vecOptions.push_back(pEntry); |
||||
} |
||||
} |
||||
|
||||
vecDialogItems.push_back(std::make_unique<UiListItem>("", -1, UiFlags::ElementDisabled)); |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Previous Menu"), static_cast<int>(SpecialMenuEntry::PreviousMenu), UiFlags::ColorUiGold)); |
||||
|
||||
vecDialog.push_back(std::make_unique<UiList>(vecDialogItems, rectList.size.height / 26, rectList.position.x, rectList.position.y, rectList.size.width, 26, UiFlags::FontSize24 | UiFlags::AlignCenter)); |
||||
|
||||
UiInitList(ItemFocused, ItemSelected, EscPressed, vecDialog, true, nullptr, switchOptionExists ? 0 : 1); |
||||
|
||||
while (!endMenu) { |
||||
UiClearScreen(); |
||||
UiRenderItems(vecDialog); |
||||
UiPollAndRender(); |
||||
} |
||||
|
||||
vecDialogItems.clear(); |
||||
vecDialog.clear(); |
||||
vecOptions.clear(); |
||||
|
||||
ArtBackground.Unload(); |
||||
ArtBackgroundWidescreen.Unload(); |
||||
UnloadScrollBar(); |
||||
|
||||
if (recreateUI) { |
||||
UiInitialize(); |
||||
FreeItemGFX(); |
||||
InitItemGFX(); |
||||
if (IsHardwareCursor()) |
||||
SetHardwareCursor(CursorInfo::UnknownCursor()); |
||||
recreateUI = false; |
||||
endMenu = false; |
||||
} |
||||
} while (!endMenu); |
||||
} |
||||
|
||||
} // namespace devilution
|
||||
#include "selstart.h" |
||||
|
||||
#include "DiabloUI/diabloui.h" |
||||
#include "DiabloUI/scrollbar.h" |
||||
#include "control.h" |
||||
#include "engine/render/text_render.hpp" |
||||
#include "hwcursor.hpp" |
||||
#include "options.h" |
||||
#include "utils/language.h" |
||||
|
||||
namespace devilution { |
||||
namespace { |
||||
|
||||
bool endMenu = false; |
||||
bool recreateUI = false; |
||||
|
||||
std::vector<std::unique_ptr<UiListItem>> vecDialogItems; |
||||
std::vector<std::unique_ptr<UiItemBase>> vecDialog; |
||||
std::vector<OptionEntryBase *> vecOptions; |
||||
|
||||
char optionDescription[256]; |
||||
|
||||
Rectangle rectDescription; |
||||
|
||||
enum class SpecialMenuEntry { |
||||
None = -1, |
||||
PreviousMenu = -2, |
||||
SwitchGame = -3, |
||||
ToggleSpawn = -4, |
||||
}; |
||||
|
||||
bool IsValidEntry(OptionEntryBase *pOptionEntry) |
||||
{ |
||||
return HasNoneOf(pOptionEntry->GetFlags(), OptionEntryFlags::Invisible | (gbIsHellfire ? OptionEntryFlags::OnlyDiablo : OptionEntryFlags::OnlyHellfire)); |
||||
} |
||||
|
||||
std::vector<DrawStringFormatArg> CreateDrawStringFormatArgForEntry(OptionEntryBase *pEntry) |
||||
{ |
||||
return std::vector<DrawStringFormatArg> { |
||||
{ pEntry->GetName().data(), UiFlags::ColorUiGold }, |
||||
{ pEntry->GetValueDescription().data(), UiFlags::ColorUiSilver } |
||||
}; |
||||
} |
||||
|
||||
void ItemFocused(int value) |
||||
{ |
||||
auto &vecItem = vecDialogItems[value]; |
||||
optionDescription[0] = '\0'; |
||||
if (vecItem->m_value < 0) { |
||||
return; |
||||
} |
||||
auto *pOption = vecOptions[vecItem->m_value]; |
||||
auto paragraphs = WordWrapString(pOption->GetDescription(), rectDescription.size.width, GameFont12, 1); |
||||
strncpy(optionDescription, paragraphs.c_str(), sizeof(optionDescription)); |
||||
} |
||||
|
||||
void ItemSelected(int value) |
||||
{ |
||||
auto &vecItem = vecDialogItems[value]; |
||||
if (vecItem->m_value < 0) { |
||||
auto specialMenuEntry = static_cast<SpecialMenuEntry>(vecItem->m_value); |
||||
switch (specialMenuEntry) { |
||||
case SpecialMenuEntry::None: |
||||
break; |
||||
case SpecialMenuEntry::PreviousMenu: |
||||
endMenu = true; |
||||
break; |
||||
case SpecialMenuEntry::SwitchGame: |
||||
gbIsHellfire = !gbIsHellfire; |
||||
endMenu = true; |
||||
recreateUI = true; |
||||
break; |
||||
case SpecialMenuEntry::ToggleSpawn: |
||||
gbIsSpawn = !gbIsSpawn; |
||||
UiSetSpawned(gbIsSpawn); |
||||
endMenu = true; |
||||
recreateUI = true; |
||||
break; |
||||
} |
||||
return; |
||||
} |
||||
|
||||
auto *pOption = vecOptions[vecItem->m_value]; |
||||
switch (pOption->GetType()) { |
||||
case OptionEntryType::Boolean: { |
||||
auto *pOptionBoolean = static_cast<OptionEntryBoolean *>(pOption); |
||||
pOptionBoolean->SetValue(!**pOptionBoolean); |
||||
} break; |
||||
case OptionEntryType::List: { |
||||
auto *pOptionList = static_cast<OptionEntryListBase *>(pOption); |
||||
size_t nextIndex = pOptionList->GetActiveListIndex() + 1; |
||||
if (nextIndex >= pOptionList->GetListSize()) |
||||
nextIndex = 0; |
||||
pOptionList->SetActiveListIndex(nextIndex); |
||||
} break; |
||||
} |
||||
vecDialogItems[value]->args.clear(); |
||||
for (auto &arg : CreateDrawStringFormatArgForEntry(pOption)) |
||||
vecDialogItems[value]->args.push_back(arg); |
||||
} |
||||
|
||||
void EscPressed() |
||||
{ |
||||
endMenu = true; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
void UiSettingsMenu() |
||||
{ |
||||
endMenu = false; |
||||
|
||||
do { |
||||
LoadBackgroundArt("ui_art\\black.pcx"); |
||||
LoadScrollBar(); |
||||
UiAddBackground(&vecDialog); |
||||
UiAddLogo(&vecDialog); |
||||
|
||||
Rectangle rectList = { { PANEL_LEFT + 50, (UI_OFFSET_Y + 204) }, { 540, 208 } }; |
||||
rectDescription = { { PANEL_LEFT + 24, rectList.position.y + rectList.size.height + 20 }, { 590, 35 } }; |
||||
|
||||
optionDescription[0] = '\0'; |
||||
|
||||
const char *titleText = _("Settings"); |
||||
vecDialog.push_back(std::make_unique<UiArtText>(titleText, MakeSdlRect(PANEL_LEFT, UI_OFFSET_Y + 161, PANEL_WIDTH, 35), UiFlags::FontSize30 | UiFlags::ColorUiSilver | UiFlags::AlignCenter, 8)); |
||||
vecDialog.push_back(std::make_unique<UiScrollbar>(&ArtScrollBarBackground, &ArtScrollBarThumb, &ArtScrollBarArrow, MakeSdlRect(rectList.position.x + rectList.size.width + 5, rectList.position.y, 25, rectList.size.height))); |
||||
vecDialog.push_back(std::make_unique<UiArtText>(optionDescription, MakeSdlRect(rectDescription), UiFlags::FontSize12 | UiFlags::ColorUiSilverDark | UiFlags::AlignCenter, 1)); |
||||
|
||||
if (diabdat_mpq && hellfire_mpq) |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>(gbIsHellfire ? _("Switch to Diablo") : _("Switch to Hellfire"), static_cast<int>(SpecialMenuEntry::SwitchGame), UiFlags::ColorUiGold)); |
||||
if (diabdat_mpq) |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>(gbIsSpawn ? _("Switch to Fullgame") : _("Switch to Shareware"), static_cast<int>(SpecialMenuEntry::ToggleSpawn), UiFlags::ColorUiGold)); |
||||
|
||||
bool switchOptionExists = vecDialogItems.size() > 0; |
||||
int catCount = switchOptionExists ? 1 : 0; |
||||
for (auto *pCategory : sgOptions.GetCategories()) { |
||||
bool categoryCreated = false; |
||||
for (auto *pEntry : pCategory->GetEntries()) { |
||||
if (!IsValidEntry(pEntry)) |
||||
continue; |
||||
if (!categoryCreated) { |
||||
if (catCount > 0) |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>("", -1, UiFlags::ElementDisabled)); |
||||
catCount += 1; |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>(pCategory->GetName().data(), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorWhitegold | UiFlags::ElementDisabled)); |
||||
categoryCreated = true; |
||||
} |
||||
auto formatArgs = CreateDrawStringFormatArgForEntry(pEntry); |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>("{}: {}", formatArgs, vecOptions.size(), UiFlags::ColorUiGold)); |
||||
vecOptions.push_back(pEntry); |
||||
} |
||||
} |
||||
|
||||
vecDialogItems.push_back(std::make_unique<UiListItem>("", -1, UiFlags::ElementDisabled)); |
||||
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Previous Menu"), static_cast<int>(SpecialMenuEntry::PreviousMenu), UiFlags::ColorUiGold)); |
||||
|
||||
vecDialog.push_back(std::make_unique<UiList>(vecDialogItems, rectList.size.height / 26, rectList.position.x, rectList.position.y, rectList.size.width, 26, UiFlags::FontSize24 | UiFlags::AlignCenter)); |
||||
|
||||
UiInitList(ItemFocused, ItemSelected, EscPressed, vecDialog, true, nullptr, switchOptionExists ? 0 : 1); |
||||
|
||||
while (!endMenu) { |
||||
UiClearScreen(); |
||||
UiRenderItems(vecDialog); |
||||
UiPollAndRender(); |
||||
} |
||||
|
||||
vecDialogItems.clear(); |
||||
vecDialog.clear(); |
||||
vecOptions.clear(); |
||||
|
||||
ArtBackground.Unload(); |
||||
ArtBackgroundWidescreen.Unload(); |
||||
UnloadScrollBar(); |
||||
|
||||
if (recreateUI) { |
||||
UiInitialize(); |
||||
FreeItemGFX(); |
||||
InitItemGFX(); |
||||
if (IsHardwareCursor()) |
||||
SetHardwareCursor(CursorInfo::UnknownCursor()); |
||||
recreateUI = false; |
||||
endMenu = false; |
||||
} |
||||
} while (!endMenu); |
||||
} |
||||
|
||||
} // namespace devilution
|
||||
|
||||
Loading…
Reference in new issue