Browse Source

Introduce OptionEntry/OptionCategory

pull/3594/head
obligaron 4 years ago committed by Anders Jenbo
parent
commit
5e3b54e98e
  1. 126
      Source/options.cpp
  2. 157
      Source/options.h

126
Source/options.cpp

@ -215,6 +215,12 @@ bool sbWasOptionsLoaded = false;
void LoadOptions()
{
for (OptionCategoryBase *pCategory : sgOptions.GetCategories()) {
for (OptionEntryBase *pEntry : pCategory->GetEntries()) {
pEntry->LoadFromIni(pCategory->GetKey());
}
}
sgOptions.Diablo.bIntro = GetIniBool("Diablo", "Intro", true);
sgOptions.Diablo.lastSinglePlayerHero = GetIniInt("Diablo", "LastSinglePlayerHero", 0);
sgOptions.Diablo.lastMultiplayerHero = GetIniInt("Diablo", "LastMultiplayerHero", 0);
@ -373,6 +379,12 @@ void LoadOptions()
void SaveOptions()
{
for (OptionCategoryBase *pCategory : sgOptions.GetCategories()) {
for (OptionEntryBase *pEntry : pCategory->GetEntries()) {
pEntry->SaveToIni(pCategory->GetKey());
}
}
SetIniValue("Diablo", "Intro", sgOptions.Diablo.bIntro);
SetIniValue("Diablo", "LastSinglePlayerHero", sgOptions.Diablo.lastSinglePlayerHero);
SetIniValue("Diablo", "LastMultiplayerHero", sgOptions.Diablo.lastMultiplayerHero);
@ -459,4 +471,118 @@ void SaveOptions()
SaveIni();
}
string_view OptionEntryBase::GetName() const
{
return _(name.data());
}
string_view OptionEntryBase::GetDescription() const
{
return _(description.data());
}
OptionEntryFlags OptionEntryBase::GetFlags() const
{
return flags;
}
void OptionEntryBase::SetValueChangedCallback(std::function<void()> callback)
{
this->callback = callback;
}
void OptionEntryBase::NotifyValueChanged()
{
if (callback)
callback();
}
void OptionEntryBoolean::LoadFromIni(string_view category)
{
value = GetIniBool(category.data(), key.data(), defaultValue);
}
void OptionEntryBoolean::SaveToIni(string_view category) const
{
SetIniValue(category.data(), key.data(), value);
}
bool OptionEntryBoolean::operator*() const
{
return value;
}
void OptionEntryBoolean::SetValue(bool value)
{
this->value = value;
this->NotifyValueChanged();
}
OptionEntryType OptionEntryBoolean::GetType() const
{
return OptionEntryType::Boolean;
}
string_view OptionEntryBoolean::GetValueDescription() const
{
return value ? _("ON") : _("OFF");
}
OptionEntryType OptionEntryListBase::GetType() const
{
return OptionEntryType::List;
}
string_view OptionEntryListBase::GetValueDescription() const
{
return GetListDescription(GetActiveListIndex());
}
void OptionEntryEnumBase::LoadFromIni(string_view category)
{
value = GetIniInt(category.data(), key.data(), defaultValue);
}
void OptionEntryEnumBase::SaveToIni(string_view category) const
{
SetIniValue(category.data(), key.data(), value);
}
int OptionEntryEnumBase::GetValueInternal()
{
return value;
}
void OptionEntryEnumBase::AddEntry(int value, string_view name)
{
entryValues.push_back(value);
entryNames.push_back(name);
}
size_t OptionEntryEnumBase::GetListSize() const
{
return entryValues.size();
}
string_view OptionEntryEnumBase::GetListDescription(size_t index) const
{
return _(entryNames[index].data());
}
size_t OptionEntryEnumBase::GetActiveListIndex() const
{
auto iterator = std::find(entryValues.begin(), entryValues.end(), value);
if (iterator == entryValues.end())
return 0;
return std::distance(entryValues.begin(), iterator);
}
void OptionEntryEnumBase::SetActiveListIndex(size_t index)
{
this->value = entryValues[index];
this->NotifyValueChanged();
}
OptionCategoryBase::OptionCategoryBase(string_view key, string_view name, string_view description)
: key(key)
, name(name)
, description(description)
{
}
string_view OptionCategoryBase::GetKey() const
{
return key;
}
string_view OptionCategoryBase::GetName() const
{
return _(name.data());
}
string_view OptionCategoryBase::GetDescription() const
{
return _(description.data());
}
} // namespace devilution

157
Source/options.h

@ -5,6 +5,8 @@
#include <SDL_version.h>
#include "pack.h"
#include "utils/enum_traits.h"
#include "utils/stdcompat/string_view.hpp"
namespace devilution {
@ -14,6 +16,156 @@ enum class StartUpGameOption {
Diablo,
};
enum class OptionEntryType {
Boolean,
List,
};
enum class OptionEntryFlags {
/** @brief No special logic. */
None = 0,
/** @brief Shouldn't be shown in settings dialog. */
Invisible = 1 << 0,
/** @brief Need to restart the current running game (single- or multiplayer) to take effect. */
CantChangeInGame = 1 << 1,
/** @brief Need to restart the current running multiplayer game to take effect. */
CantChangeInMultiPlayer = 1 << 2,
/** @brief Option is only relevant for Hellfire. */
OnlyHellfire = 1 << 3,
/** @brief Option is only relevant for Diablo. */
OnlyDiablo = 1 << 4,
};
use_enum_as_flags(OptionEntryFlags);
class OptionEntryBase {
public:
OptionEntryBase(string_view key, OptionEntryFlags flags, string_view name, string_view description)
: key(key)
, flags(flags)
, name(name)
, description(description)
{
}
[[nodiscard]] string_view GetName() const;
[[nodiscard]] string_view GetDescription() const;
[[nodiscard]] virtual OptionEntryType GetType() const = 0;
[[nodiscard]] OptionEntryFlags GetFlags() const;
void SetValueChangedCallback(std::function<void()> callback);
[[nodiscard]] virtual string_view GetValueDescription() const = 0;
virtual void LoadFromIni(string_view category) = 0;
virtual void SaveToIni(string_view category) const = 0;
protected:
string_view key;
string_view name;
string_view description;
OptionEntryFlags flags;
void NotifyValueChanged();
private:
std::function<void()> callback;
};
class OptionEntryBoolean : public OptionEntryBase {
public:
OptionEntryBoolean(string_view key, OptionEntryFlags flags, string_view name, string_view description, bool defaultValue)
: OptionEntryBase(key, flags, name, description)
, defaultValue(defaultValue)
, value(defaultValue)
{
}
[[nodiscard]] bool operator*() const;
void SetValue(bool value);
[[nodiscard]] OptionEntryType GetType() const override;
[[nodiscard]] string_view GetValueDescription() const override;
void LoadFromIni(string_view category) override;
void SaveToIni(string_view category) const override;
private:
bool value;
bool defaultValue;
};
class OptionEntryListBase : public OptionEntryBase {
public:
[[nodiscard]] virtual size_t GetListSize() const = 0;
[[nodiscard]] virtual string_view GetListDescription(size_t index) const = 0;
[[nodiscard]] virtual size_t GetActiveListIndex() const = 0;
virtual void SetActiveListIndex(size_t index) = 0;
[[nodiscard]] OptionEntryType GetType() const override;
[[nodiscard]] string_view GetValueDescription() const override;
protected:
OptionEntryListBase(string_view key, OptionEntryFlags flags, string_view name, string_view description)
: OptionEntryBase(key, flags, name, description)
{
}
};
class OptionEntryEnumBase : public OptionEntryListBase {
public:
void LoadFromIni(string_view category) override;
void SaveToIni(string_view category) const override;
[[nodiscard]] virtual size_t GetListSize() const override;
[[nodiscard]] virtual string_view GetListDescription(size_t index) const override;
[[nodiscard]] size_t GetActiveListIndex() const override;
void SetActiveListIndex(size_t index) override;
protected:
OptionEntryEnumBase(string_view key, OptionEntryFlags flags, string_view name, string_view description, int defaultValue)
: OptionEntryListBase(key, flags, name, description)
, defaultValue(defaultValue)
, value(defaultValue)
{
}
int GetValueInternal();
void AddEntry(int value, string_view name);
private:
int value;
int defaultValue;
std::vector<string_view> entryNames;
std::vector<int> entryValues;
};
template <typename T>
class OptionEntryEnum : public OptionEntryEnumBase {
public:
OptionEntryEnum(string_view key, OptionEntryFlags flags, string_view name, string_view description, T defaultValue, std::initializer_list<std::pair<T, string_view>> entries)
: OptionEntryEnumBase(key, flags, name, description, static_cast<int>(defaultValue))
{
for (auto entry : entries) {
AddEntry(static_cast<int>(entry.first), entry.second);
}
}
[[nodiscard]] T operator*() const
{
return static_cast<T>(GetValueInternal());
}
};
struct OptionCategoryBase {
OptionCategoryBase(string_view key, string_view name, string_view description);
[[nodiscard]] string_view GetKey() const;
[[nodiscard]] string_view GetName() const;
[[nodiscard]] string_view GetDescription() const;
virtual std::vector<OptionEntryBase *> GetEntries() = 0;
protected:
string_view key;
string_view name;
string_view description;
};
struct DiabloOptions {
/** @brief Play game intro video on startup. */
bool bIntro;
@ -184,6 +336,11 @@ struct Options {
NetworkOptions Network;
ChatOptions Chat;
LanguageOptions Language;
[[nodiscard]] std::vector<OptionCategoryBase *> GetCategories()
{
return {};
}
};
bool GetIniValue(const char *sectionName, const char *keyName, char *string, int stringSize, const char *defaultString = "");

Loading…
Cancel
Save