Browse Source

Implement settings menu

pull/3594/head
obligaron 4 years ago committed by Anders Jenbo
parent
commit
f02264f69c
  1. 2
      CMakeLists.txt
  2. 4
      Source/DiabloUI/diabloui.h
  3. 66
      Source/DiabloUI/extrasmenu.cpp
  4. 3
      Source/DiabloUI/mainmenu.cpp
  5. 174
      Source/DiabloUI/settingsmenu.cpp
  6. 18
      Source/DiabloUI/settingsmenu.h
  7. 51
      Source/menu.cpp

2
CMakeLists.txt

@ -492,10 +492,10 @@ set(libdevilutionx_SRCS
Source/DiabloUI/diabloui.cpp
Source/DiabloUI/dialogs.cpp
Source/DiabloUI/errorart.cpp
Source/DiabloUI/extrasmenu.cpp
Source/DiabloUI/mainmenu.cpp
Source/DiabloUI/progress.cpp
Source/DiabloUI/scrollbar.cpp
Source/DiabloUI/settingsmenu.cpp
Source/DiabloUI/selconn.cpp
Source/DiabloUI/selgame.cpp
Source/DiabloUI/selhero.cpp

4
Source/DiabloUI/diabloui.h

@ -33,9 +33,7 @@ enum _mainmenu_selections : uint8_t {
MAINMENU_MULTIPLAYER,
MAINMENU_REPLAY_INTRO,
MAINMENU_SHOW_SUPPORT,
MAINMENU_EXTRAS,
MAINMENU_SWITCHGAME,
MAINMENU_TOGGLESPAWN,
MAINMENU_SETTINGS,
MAINMENU_SHOW_CREDITS,
MAINMENU_EXIT_DIABLO,
MAINMENU_ATTRACT_MODE,

66
Source/DiabloUI/extrasmenu.cpp

@ -1,66 +0,0 @@
#include "selstart.h"
#include "control.h"
#include "DiabloUI/diabloui.h"
#include "options.h"
#include "utils/language.h"
namespace devilution {
namespace {
bool endMenu;
std::vector<std::unique_ptr<UiListItem>> vecDialogItems;
std::vector<std::unique_ptr<UiItemBase>> vecDialog;
Art artLogo;
_mainmenu_selections selectionExtrasMenu;
void ItemSelected(int value)
{
selectionExtrasMenu = static_cast<_mainmenu_selections>(vecDialogItems[value]->m_value);
endMenu = true;
}
void EscPressed()
{
selectionExtrasMenu = MAINMENU_NONE;
endMenu = true;
}
} // namespace
_mainmenu_selections UiExtrasMenu()
{
LoadBackgroundArt("ui_art\\black.pcx");
UiAddBackground(&vecDialog);
UiAddLogo(&vecDialog);
if (diabdat_mpq && hellfire_mpq)
vecDialogItems.push_back(std::make_unique<UiListItem>(gbIsHellfire ? _("Switch to Diablo") : _("Switch to Hellfire"), MAINMENU_SWITCHGAME));
if (diabdat_mpq)
vecDialogItems.push_back(std::make_unique<UiListItem>(gbIsSpawn ? _("Switch to Fullgame") : _("Switch to Shareware"), MAINMENU_TOGGLESPAWN));
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Replay Intro"), MAINMENU_REPLAY_INTRO));
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Support"), MAINMENU_SHOW_SUPPORT));
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Previous Menu"), MAINMENU_NONE));
vecDialog.push_back(std::make_unique<UiList>(vecDialogItems, PANEL_LEFT + 34, (UI_OFFSET_Y + 240), 570, 43, UiFlags::AlignCenter | UiFlags::FontSize42 | UiFlags::ColorUiGold, 5));
UiInitList(vecDialogItems.size(), nullptr, ItemSelected, EscPressed, vecDialog, true);
endMenu = false;
while (!endMenu) {
UiClearScreen();
UiRenderItems(vecDialog);
UiPollAndRender();
}
ArtBackground.Unload();
ArtBackgroundWidescreen.Unload();
vecDialogItems.clear();
vecDialog.clear();
return selectionExtrasMenu;
}
} // namespace devilution

3
Source/DiabloUI/mainmenu.cpp

@ -35,7 +35,8 @@ void MainmenuLoad(const char *name, void (*fnSound)(const char *file))
vecMenuItems.push_back(std::make_unique<UiListItem>(_("Single Player"), MAINMENU_SINGLE_PLAYER));
vecMenuItems.push_back(std::make_unique<UiListItem>(_("Multi Player"), MAINMENU_MULTIPLAYER));
vecMenuItems.push_back(std::make_unique<UiListItem>(_("Extras"), MAINMENU_EXTRAS));
vecMenuItems.push_back(std::make_unique<UiListItem>(_("Settings"), MAINMENU_SETTINGS));
vecMenuItems.push_back(std::make_unique<UiListItem>(_("Support"), MAINMENU_SHOW_SUPPORT));
vecMenuItems.push_back(std::make_unique<UiListItem>(_("Show Credits"), MAINMENU_SHOW_CREDITS));
vecMenuItems.push_back(std::make_unique<UiListItem>(gbIsHellfire ? _("Exit Hellfire") : _("Exit Diablo"), MAINMENU_EXIT_DIABLO));

174
Source/DiabloUI/settingsmenu.cpp

@ -0,0 +1,174 @@
#include "selstart.h"
#include "control.h"
#include "DiabloUI/diabloui.h"
#include "DiabloUI/scrollbar.h"
#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));
}
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::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 + 1]->m_text = pOption->GetValueDescription().data();
}
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;
}
vecDialogItems.push_back(std::make_unique<UiListItem>(pEntry->GetName().data(), vecOptions.size(), UiFlags::ColorUiGold | UiFlags::NeedsNextElement));
vecDialogItems.push_back(std::make_unique<UiListItem>(pEntry->GetValueDescription().data(), vecOptions.size(), UiFlags::ColorUiSilver | UiFlags::ElementDisabled));
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.position.x, rectList.position.y, rectList.size.width, 26, UiFlags::FontSize24 | UiFlags::AlignCenter));
UiInitList(rectList.size.height / 26, 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

18
Source/DiabloUI/extrasmenu.h → Source/DiabloUI/settingsmenu.h

@ -1,9 +1,9 @@
#pragma once
#include "DiabloUI/diabloui.h"
namespace devilution {
_mainmenu_selections UiExtrasMenu();
} // namespace devilution
#pragma once
#include "DiabloUI/diabloui.h"
namespace devilution {
void UiSettingsMenu();
} // namespace devilution

51
Source/menu.cpp

@ -5,10 +5,8 @@
*/
#include "DiabloUI/diabloui.h"
#include "DiabloUI/extrasmenu.h"
#include "DiabloUI/selok.h"
#include "DiabloUI/settingsmenu.h"
#include "engine/demomode.h"
#include "hwcursor.hpp"
#include "init.h"
#include "movie.h"
#include "options.h"
@ -141,18 +139,16 @@ void mainmenu_wait_for_button_sound()
void mainmenu_loop()
{
bool done;
_mainmenu_selections menu = MAINMENU_NONE;
RefreshMusic();
done = false;
do {
if (menu == MAINMENU_NONE) {
if (demo::IsRunning())
menu = MAINMENU_SINGLE_PLAYER;
else if (!UiMainMenuDialog(gszProductName, &menu, effects_play_sound, 30))
app_fatal("%s", _("Unable to display mainmenu"));
}
_mainmenu_selections menu = MAINMENU_NONE;
if (demo::IsRunning())
menu = MAINMENU_SINGLE_PLAYER;
else if (!UiMainMenuDialog(gszProductName, &menu, effects_play_sound, 30))
app_fatal("%s", _("Unable to display mainmenu"));
switch (menu) {
case MAINMENU_NONE:
@ -160,60 +156,29 @@ void mainmenu_loop()
case MAINMENU_SINGLE_PLAYER:
if (!InitSinglePlayerMenu())
done = true;
menu = MAINMENU_NONE;
break;
case MAINMENU_MULTIPLAYER:
if (!InitMultiPlayerMenu())
done = true;
menu = MAINMENU_NONE;
break;
case MAINMENU_ATTRACT_MODE:
if (gbIsSpawn && !diabdat_mpq)
done = false;
else if (gbActive)
PlayIntro();
menu = MAINMENU_NONE;
break;
case MAINMENU_REPLAY_INTRO:
if (gbIsSpawn && !diabdat_mpq && !hellfire_mpq) {
UiSelOkDialog(nullptr, _(/* TRANSLATORS: Error Message when a Shareware User clicks on "Replay Intro" in the Main Menu */ "The Diablo introduction cinematic is only available in the full retail version of Diablo. Visit https://www.gog.com/game/diablo to purchase."), true);
} else if (gbActive) {
mainmenu_wait_for_button_sound();
PlayIntro();
}
menu = MAINMENU_EXTRAS;
break;
case MAINMENU_SHOW_CREDITS:
UiCreditsDialog();
menu = MAINMENU_NONE;
break;
case MAINMENU_SHOW_SUPPORT:
UiSupportDialog();
menu = MAINMENU_EXTRAS;
break;
case MAINMENU_EXIT_DIABLO:
mainmenu_wait_for_button_sound();
done = true;
break;
case MAINMENU_EXTRAS:
menu = UiExtrasMenu();
break;
case MAINMENU_SWITCHGAME:
gbIsHellfire = !gbIsHellfire;
sgOptions.Hellfire.startUpGameOption = gbIsHellfire ? StartUpGameOption::Hellfire : StartUpGameOption::Diablo;
UiInitialize();
FreeItemGFX();
InitItemGFX();
if (IsHardwareCursor())
SetHardwareCursor(CursorInfo::UnknownCursor());
RefreshMusic();
menu = MAINMENU_NONE;
break;
case MAINMENU_TOGGLESPAWN:
gbIsSpawn = !gbIsSpawn;
UiSetSpawned(gbIsSpawn);
RefreshMusic();
menu = MAINMENU_NONE;
case MAINMENU_SETTINGS:
UiSettingsMenu();
break;
}
} while (!done);

Loading…
Cancel
Save