Merge branch 'settings_values_index' into 'master'

Use typed settings storage for settings window (#6876)

See merge request OpenMW/openmw!2997
simplify_debugging
psi29a 2 years ago
commit c15710c35b

@ -93,19 +93,49 @@ namespace
benchmark::DoNotOptimize(Settings::water().mReflectionDetail.get()); benchmark::DoNotOptimize(Settings::water().mReflectionDetail.get());
} }
} }
void settingsStorageGet(benchmark::State& state)
{
for (auto _ : state)
{
benchmark::DoNotOptimize(Settings::get<float>("Fog", "sky blending start"));
}
}
void settingsStorageGet2(benchmark::State& state)
{
for (auto _ : state)
{
benchmark::DoNotOptimize(Settings::get<bool>("Post Processing", "transparent postpass"));
benchmark::DoNotOptimize(Settings::get<float>("Camera", "near clip"));
}
}
void settingsStorageGet3(benchmark::State& state)
{
for (auto _ : state)
{
benchmark::DoNotOptimize(Settings::get<bool>("Post Processing", "transparent postpass"));
benchmark::DoNotOptimize(Settings::get<float>("Camera", "near clip"));
benchmark::DoNotOptimize(Settings::get<int>("Water", "reflection detail"));
}
}
} }
BENCHMARK(settingsManager); BENCHMARK(settingsManager);
BENCHMARK(localStatic); BENCHMARK(localStatic);
BENCHMARK(settingsStorage); BENCHMARK(settingsStorage);
BENCHMARK(settingsStorageGet);
BENCHMARK(settingsManager2); BENCHMARK(settingsManager2);
BENCHMARK(localStatic2); BENCHMARK(localStatic2);
BENCHMARK(settingsStorage2); BENCHMARK(settingsStorage2);
BENCHMARK(settingsStorageGet2);
BENCHMARK(settingsManager3); BENCHMARK(settingsManager3);
BENCHMARK(localStatic3); BENCHMARK(localStatic3);
BENCHMARK(settingsStorage3); BENCHMARK(settingsStorage3);
BENCHMARK(settingsStorageGet3);
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
@ -115,14 +145,14 @@ int main(int argc, char* argv[])
Settings::SettingsFileParser parser; Settings::SettingsFileParser parser;
parser.loadSettingsFile(settingsDefaultPath, Settings::Manager::mDefaultSettings); parser.loadSettingsFile(settingsDefaultPath, Settings::Manager::mDefaultSettings);
Settings::Values::initDefaults(); Settings::StaticValues::initDefaults();
Settings::Manager::mUserSettings = Settings::Manager::mDefaultSettings; Settings::Manager::mUserSettings = Settings::Manager::mDefaultSettings;
Settings::Manager::mUserSettings.erase({ "Camera", "near clip" }); Settings::Manager::mUserSettings.erase({ "Camera", "near clip" });
Settings::Manager::mUserSettings.erase({ "Post Processing", "transparent postpass" }); Settings::Manager::mUserSettings.erase({ "Post Processing", "transparent postpass" });
Settings::Manager::mUserSettings.erase({ "Water", "reflection detail" }); Settings::Manager::mUserSettings.erase({ "Water", "reflection detail" });
Settings::Values::init(); Settings::StaticValues::init();
benchmark::Initialize(&argc, argv); benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks(); benchmark::RunSpecifiedBenchmarks();

@ -168,9 +168,8 @@ namespace MWGui
std::string type = getSettingType(current); std::string type = getSettingType(current);
if (type == checkButtonType) if (type == checkButtonType)
{ {
std::string initialValue const std::string initialValue
= Settings::Manager::getBool(getSettingName(current), getSettingCategory(current)) = Settings::get<bool>(getSettingCategory(current), getSettingName(current)) ? "#{Interface:On}"
? "#{Interface:On}"
: "#{Interface:Off}"; : "#{Interface:Off}";
current->castType<MyGUI::Button>()->setCaptionWithReplacing(initialValue); current->castType<MyGUI::Button>()->setCaptionWithReplacing(initialValue);
if (init) if (init)
@ -186,22 +185,28 @@ namespace MWGui
// TODO: ScrollBar isn't meant for this. should probably use a dedicated FloatSlider widget // TODO: ScrollBar isn't meant for this. should probably use a dedicated FloatSlider widget
float min, max; float min, max;
getSettingMinMax(scroll, min, max); getSettingMinMax(scroll, min, max);
float value = Settings::Manager::getFloat(getSettingName(current), getSettingCategory(current)); float value;
if (valueType == "Cell") if (valueType == "Cell")
{ {
value = Settings::get<float>(getSettingCategory(current), getSettingName(current));
std::stringstream ss; std::stringstream ss;
ss << std::fixed << std::setprecision(2) << value / Constants::CellSizeInUnits; ss << std::fixed << std::setprecision(2) << value / Constants::CellSizeInUnits;
valueStr = ss.str(); valueStr = ss.str();
} }
else if (valueType == "Float") else if (valueType == "Float")
{ {
value = Settings::get<float>(getSettingCategory(current), getSettingName(current));
std::stringstream ss; std::stringstream ss;
ss << std::fixed << std::setprecision(2) << value; ss << std::fixed << std::setprecision(2) << value;
valueStr = ss.str(); valueStr = ss.str();
} }
else else
valueStr = MyGUI::utility::toString(int(value)); {
const int intValue = Settings::get<int>(getSettingCategory(current), getSettingName(current));
valueStr = MyGUI::utility::toString(intValue);
value = static_cast<float>(intValue);
}
value = std::clamp(value, min, max); value = std::clamp(value, min, max);
value = (value - min) / (max - min); value = (value - min) / (max - min);
@ -210,7 +215,7 @@ namespace MWGui
} }
else else
{ {
int value = Settings::Manager::getInt(getSettingName(current), getSettingCategory(current)); const int value = Settings::get<int>(getSettingCategory(current), getSettingName(current));
valueStr = MyGUI::utility::toString(value); valueStr = MyGUI::utility::toString(value);
scroll->setScrollPosition(value); scroll->setScrollPosition(value);
} }
@ -656,7 +661,7 @@ namespace MWGui
if (getSettingType(_sender) == checkButtonType) if (getSettingType(_sender) == checkButtonType)
{ {
Settings::Manager::setBool(getSettingName(_sender), getSettingCategory(_sender), newState); Settings::get<bool>(getSettingCategory(_sender), getSettingName(_sender)).set(newState);
apply(); apply();
return; return;
} }
@ -693,9 +698,10 @@ namespace MWGui
getSettingMinMax(scroller, min, max); getSettingMinMax(scroller, min, max);
value = min + (max - min) * value; value = min + (max - min) * value;
if (valueType == "Float") if (valueType == "Float")
Settings::Manager::setFloat(getSettingName(scroller), getSettingCategory(scroller), value); Settings::get<float>(getSettingCategory(scroller), getSettingName(scroller)).set(value);
else else
Settings::Manager::setInt(getSettingName(scroller), getSettingCategory(scroller), (int)value); Settings::get<int>(getSettingCategory(scroller), getSettingName(scroller))
.set(static_cast<int>(value));
if (valueType == "Cell") if (valueType == "Cell")
{ {
@ -714,7 +720,7 @@ namespace MWGui
} }
else else
{ {
Settings::Manager::setInt(getSettingName(scroller), getSettingCategory(scroller), pos); Settings::get<int>(getSettingCategory(scroller), getSettingName(scroller)).set(pos);
valueStr = MyGUI::utility::toString(pos); valueStr = MyGUI::utility::toString(pos);
} }
updateSliderLabel(scroller, valueStr); updateSliderLabel(scroller, valueStr);

@ -32,26 +32,37 @@ namespace Settings
TEST_F(SettingsValuesTest, shouldLoadFromSettingsManager) TEST_F(SettingsValuesTest, shouldLoadFromSettingsManager)
{ {
Values values; Index index;
Values values(index);
EXPECT_EQ(values.mCamera.mFieldOfView.get(), 60); EXPECT_EQ(values.mCamera.mFieldOfView.get(), 60);
} }
TEST_F(SettingsValuesTest, shouldFillIndexOnLoad)
{
Index index;
Values values(index);
EXPECT_EQ(index.get<float>("Camera", "field of view").get(), 60);
}
TEST_F(SettingsValuesTest, constructorShouldThrowExceptionOnMissingSetting) TEST_F(SettingsValuesTest, constructorShouldThrowExceptionOnMissingSetting)
{ {
Manager::mDefaultSettings.erase({ "Camera", "field of view" }); Manager::mDefaultSettings.erase({ "Camera", "field of view" });
EXPECT_THROW([] { Values values; }(), std::runtime_error); Index index;
EXPECT_THROW([&] { Values values(index); }(), std::runtime_error);
} }
TEST_F(SettingsValuesTest, constructorShouldSanitize) TEST_F(SettingsValuesTest, constructorShouldSanitize)
{ {
Manager::mUserSettings[std::make_pair("Camera", "field of view")] = "-1"; Manager::mUserSettings[std::make_pair("Camera", "field of view")] = "-1";
Values values; Index index;
Values values(index);
EXPECT_EQ(values.mCamera.mFieldOfView.get(), 1); EXPECT_EQ(values.mCamera.mFieldOfView.get(), 1);
} }
TEST_F(SettingsValuesTest, moveConstructorShouldSetDefaults) TEST_F(SettingsValuesTest, moveConstructorShouldSetDefaults)
{ {
Values defaultValues; Index index;
Values defaultValues(index);
Manager::mUserSettings.emplace(std::make_pair("Camera", "field of view"), "61"); Manager::mUserSettings.emplace(std::make_pair("Camera", "field of view"), "61");
Values values(std::move(defaultValues)); Values values(std::move(defaultValues));
EXPECT_EQ(values.mCamera.mFieldOfView.get(), 61); EXPECT_EQ(values.mCamera.mFieldOfView.get(), 61);
@ -61,15 +72,38 @@ namespace Settings
TEST_F(SettingsValuesTest, moveConstructorShouldSanitize) TEST_F(SettingsValuesTest, moveConstructorShouldSanitize)
{ {
Values defaultValues; Index index;
Values defaultValues(index);
Manager::mUserSettings[std::make_pair("Camera", "field of view")] = "-1"; Manager::mUserSettings[std::make_pair("Camera", "field of view")] = "-1";
Values values(std::move(defaultValues)); Values values(std::move(defaultValues));
EXPECT_EQ(values.mCamera.mFieldOfView.get(), 1); EXPECT_EQ(values.mCamera.mFieldOfView.get(), 1);
} }
TEST_F(SettingsValuesTest, findShouldThrowExceptionOnTypeMismatch)
{
Index index;
Values values(index);
EXPECT_THROW(index.find<int>("Camera", "field of view"), std::invalid_argument);
}
TEST_F(SettingsValuesTest, findShouldReturnNullptrForAbsentSetting)
{
Index index;
Values values(index);
EXPECT_EQ(index.find<int>("foo", "bar"), nullptr);
}
TEST_F(SettingsValuesTest, getShouldThrowExceptionForAbsentSetting)
{
Index index;
Values values(index);
EXPECT_THROW(index.get<int>("foo", "bar").get(), std::invalid_argument);
}
TEST_F(SettingsValuesTest, setShouldChangeManagerUserSettings) TEST_F(SettingsValuesTest, setShouldChangeManagerUserSettings)
{ {
Values values; Index index;
Values values(index);
values.mCamera.mFieldOfView.set(42); values.mCamera.mFieldOfView.set(42);
EXPECT_EQ(Manager::mUserSettings.at({ "Camera", "field of view" }), "42"); EXPECT_EQ(Manager::mUserSettings.at({ "Camera", "field of view" }), "42");
EXPECT_THAT(Manager::mChangedSettings, ElementsAre(std::make_pair("Camera", "field of view"))); EXPECT_THAT(Manager::mChangedSettings, ElementsAre(std::make_pair("Camera", "field of view")));
@ -77,7 +111,8 @@ namespace Settings
TEST_F(SettingsValuesTest, setShouldNotChangeManagerChangedSettingsForNoChange) TEST_F(SettingsValuesTest, setShouldNotChangeManagerChangedSettingsForNoChange)
{ {
Values values; Index index;
Values values(index);
values.mCamera.mFieldOfView.set(values.mCamera.mFieldOfView.get()); values.mCamera.mFieldOfView.set(values.mCamera.mFieldOfView.get());
EXPECT_THAT(Manager::mChangedSettings, ElementsAre()); EXPECT_THAT(Manager::mChangedSettings, ElementsAre());
} }

@ -14,17 +14,19 @@
namespace Settings namespace Settings
{ {
struct CameraCategory struct CameraCategory : WithIndex
{ {
SettingValue<float> mNearClip{ "Camera", "near clip", makeMaxSanitizerFloat(0.005f) }; using WithIndex::WithIndex;
SettingValue<bool> mSmallFeatureCulling{ "Camera", "small feature culling" };
SettingValue<float> mSmallFeatureCullingPixelSize{ "Camera", "small feature culling pixel size", SettingValue<float> mNearClip{ mIndex, "Camera", "near clip", makeMaxSanitizerFloat(0.005f) };
SettingValue<bool> mSmallFeatureCulling{ mIndex, "Camera", "small feature culling" };
SettingValue<float> mSmallFeatureCullingPixelSize{ mIndex, "Camera", "small feature culling pixel size",
makeMaxStrictSanitizerFloat(0) }; makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mViewingDistance{ "Camera", "viewing distance", makeMaxStrictSanitizerFloat(0) }; SettingValue<float> mViewingDistance{ mIndex, "Camera", "viewing distance", makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mFieldOfView{ "Camera", "field of view", makeClampSanitizerFloat(1, 179) }; SettingValue<float> mFieldOfView{ mIndex, "Camera", "field of view", makeClampSanitizerFloat(1, 179) };
SettingValue<float> mFirstPersonFieldOfView{ "Camera", "first person field of view", SettingValue<float> mFirstPersonFieldOfView{ mIndex, "Camera", "first person field of view",
makeClampSanitizerFloat(1, 179) }; makeClampSanitizerFloat(1, 179) };
SettingValue<bool> mReverseZ{ "Camera", "reverse z" }; SettingValue<bool> mReverseZ{ mIndex, "Camera", "reverse z" };
}; };
} }

@ -14,22 +14,25 @@
namespace Settings namespace Settings
{ {
struct CellsCategory struct CellsCategory : WithIndex
{ {
SettingValue<bool> mPreloadEnabled{ "Cells", "preload enabled" }; using WithIndex::WithIndex;
SettingValue<int> mPreloadNumThreads{ "Cells", "preload num threads", makeMaxSanitizerInt(1) };
SettingValue<bool> mPreloadExteriorGrid{ "Cells", "preload exterior grid" }; SettingValue<bool> mPreloadEnabled{ mIndex, "Cells", "preload enabled" };
SettingValue<bool> mPreloadFastTravel{ "Cells", "preload fast travel" }; SettingValue<int> mPreloadNumThreads{ mIndex, "Cells", "preload num threads", makeMaxSanitizerInt(1) };
SettingValue<bool> mPreloadDoors{ "Cells", "preload doors" }; SettingValue<bool> mPreloadExteriorGrid{ mIndex, "Cells", "preload exterior grid" };
SettingValue<float> mPreloadDistance{ "Cells", "preload distance", makeMaxStrictSanitizerFloat(0) }; SettingValue<bool> mPreloadFastTravel{ mIndex, "Cells", "preload fast travel" };
SettingValue<bool> mPreloadInstances{ "Cells", "preload instances" }; SettingValue<bool> mPreloadDoors{ mIndex, "Cells", "preload doors" };
SettingValue<int> mPreloadCellCacheMin{ "Cells", "preload cell cache min", makeMaxSanitizerInt(1) }; SettingValue<float> mPreloadDistance{ mIndex, "Cells", "preload distance", makeMaxStrictSanitizerFloat(0) };
SettingValue<int> mPreloadCellCacheMax{ "Cells", "preload cell cache max", makeMaxSanitizerInt(1) }; SettingValue<bool> mPreloadInstances{ mIndex, "Cells", "preload instances" };
SettingValue<float> mPreloadCellExpiryDelay{ "Cells", "preload cell expiry delay", makeMaxSanitizerFloat(0) }; SettingValue<int> mPreloadCellCacheMin{ mIndex, "Cells", "preload cell cache min", makeMaxSanitizerInt(1) };
SettingValue<float> mPredictionTime{ "Cells", "prediction time", makeMaxSanitizerFloat(0) }; SettingValue<int> mPreloadCellCacheMax{ mIndex, "Cells", "preload cell cache max", makeMaxSanitizerInt(1) };
SettingValue<float> mCacheExpiryDelay{ "Cells", "cache expiry delay", makeMaxSanitizerFloat(0) }; SettingValue<float> mPreloadCellExpiryDelay{ mIndex, "Cells", "preload cell expiry delay",
SettingValue<float> mTargetFramerate{ "Cells", "target framerate", makeMaxStrictSanitizerFloat(0) }; makeMaxSanitizerFloat(0) };
SettingValue<int> mPointersCacheSize{ "Cells", "pointers cache size", makeClampSanitizerInt(40, 1000) }; SettingValue<float> mPredictionTime{ mIndex, "Cells", "prediction time", makeMaxSanitizerFloat(0) };
SettingValue<float> mCacheExpiryDelay{ mIndex, "Cells", "cache expiry delay", makeMaxSanitizerFloat(0) };
SettingValue<float> mTargetFramerate{ mIndex, "Cells", "target framerate", makeMaxStrictSanitizerFloat(0) };
SettingValue<int> mPointersCacheSize{ mIndex, "Cells", "pointers cache size", makeClampSanitizerInt(40, 1000) };
}; };
} }

@ -14,20 +14,23 @@
namespace Settings namespace Settings
{ {
struct FogCategory struct FogCategory : WithIndex
{ {
SettingValue<bool> mUseDistantFog{ "Fog", "use distant fog" }; using WithIndex::WithIndex;
SettingValue<float> mDistantLandFogStart{ "Fog", "distant land fog start" };
SettingValue<float> mDistantLandFogEnd{ "Fog", "distant land fog end" }; SettingValue<bool> mUseDistantFog{ mIndex, "Fog", "use distant fog" };
SettingValue<float> mDistantUnderwaterFogStart{ "Fog", "distant underwater fog start" }; SettingValue<float> mDistantLandFogStart{ mIndex, "Fog", "distant land fog start" };
SettingValue<float> mDistantUnderwaterFogEnd{ "Fog", "distant underwater fog end" }; SettingValue<float> mDistantLandFogEnd{ mIndex, "Fog", "distant land fog end" };
SettingValue<float> mDistantInteriorFogStart{ "Fog", "distant interior fog start" }; SettingValue<float> mDistantUnderwaterFogStart{ mIndex, "Fog", "distant underwater fog start" };
SettingValue<float> mDistantInteriorFogEnd{ "Fog", "distant interior fog end" }; SettingValue<float> mDistantUnderwaterFogEnd{ mIndex, "Fog", "distant underwater fog end" };
SettingValue<bool> mRadialFog{ "Fog", "radial fog" }; SettingValue<float> mDistantInteriorFogStart{ mIndex, "Fog", "distant interior fog start" };
SettingValue<bool> mExponentialFog{ "Fog", "exponential fog" }; SettingValue<float> mDistantInteriorFogEnd{ mIndex, "Fog", "distant interior fog end" };
SettingValue<bool> mSkyBlending{ "Fog", "sky blending" }; SettingValue<bool> mRadialFog{ mIndex, "Fog", "radial fog" };
SettingValue<float> mSkyBlendingStart{ "Fog", "sky blending start", makeClampStrictMaxSanitizerFloat(0, 1) }; SettingValue<bool> mExponentialFog{ mIndex, "Fog", "exponential fog" };
SettingValue<osg::Vec2f> mSkyRttResolution{ "Fog", "sky rtt resolution" }; SettingValue<bool> mSkyBlending{ mIndex, "Fog", "sky blending" };
SettingValue<float> mSkyBlendingStart{ mIndex, "Fog", "sky blending start",
makeClampStrictMaxSanitizerFloat(0, 1) };
SettingValue<osg::Vec2f> mSkyRttResolution{ mIndex, "Fog", "sky rtt resolution" };
}; };
} }

@ -14,56 +14,62 @@
namespace Settings namespace Settings
{ {
struct GameCategory struct GameCategory : WithIndex
{ {
SettingValue<int> mShowOwned{ "Game", "show owned", makeEnumSanitizerInt({ 0, 1, 2, 3 }) }; using WithIndex::WithIndex;
SettingValue<bool> mShowProjectileDamage{ "Game", "show projectile damage" };
SettingValue<bool> mShowMeleeInfo{ "Game", "show melee info" }; SettingValue<int> mShowOwned{ mIndex, "Game", "show owned", makeEnumSanitizerInt({ 0, 1, 2, 3 }) };
SettingValue<bool> mShowEnchantChance{ "Game", "show enchant chance" }; SettingValue<bool> mShowProjectileDamage{ mIndex, "Game", "show projectile damage" };
SettingValue<bool> mBestAttack{ "Game", "best attack" }; SettingValue<bool> mShowMeleeInfo{ mIndex, "Game", "show melee info" };
SettingValue<int> mDifficulty{ "Game", "difficulty", makeClampSanitizerInt(-500, 500) }; SettingValue<bool> mShowEnchantChance{ mIndex, "Game", "show enchant chance" };
SettingValue<int> mActorsProcessingRange{ "Game", "actors processing range", SettingValue<bool> mBestAttack{ mIndex, "Game", "best attack" };
SettingValue<int> mDifficulty{ mIndex, "Game", "difficulty", makeClampSanitizerInt(-500, 500) };
SettingValue<int> mActorsProcessingRange{ mIndex, "Game", "actors processing range",
makeClampSanitizerInt(3584, 7168) }; makeClampSanitizerInt(3584, 7168) };
SettingValue<bool> mClassicReflectedAbsorbSpellsBehavior{ "Game", "classic reflected absorb spells behavior" }; SettingValue<bool> mClassicReflectedAbsorbSpellsBehavior{ mIndex, "Game",
SettingValue<bool> mClassicCalmSpellsBehavior{ "Game", "classic calm spells behavior" }; "classic reflected absorb spells behavior" };
SettingValue<bool> mShowEffectDuration{ "Game", "show effect duration" }; SettingValue<bool> mClassicCalmSpellsBehavior{ mIndex, "Game", "classic calm spells behavior" };
SettingValue<bool> mPreventMerchantEquipping{ "Game", "prevent merchant equipping" }; SettingValue<bool> mShowEffectDuration{ mIndex, "Game", "show effect duration" };
SettingValue<bool> mEnchantedWeaponsAreMagical{ "Game", "enchanted weapons are magical" }; SettingValue<bool> mPreventMerchantEquipping{ mIndex, "Game", "prevent merchant equipping" };
SettingValue<bool> mFollowersAttackOnSight{ "Game", "followers attack on sight" }; SettingValue<bool> mEnchantedWeaponsAreMagical{ mIndex, "Game", "enchanted weapons are magical" };
SettingValue<bool> mCanLootDuringDeathAnimation{ "Game", "can loot during death animation" }; SettingValue<bool> mFollowersAttackOnSight{ mIndex, "Game", "followers attack on sight" };
SettingValue<bool> mRebalanceSoulGemValues{ "Game", "rebalance soul gem values" }; SettingValue<bool> mCanLootDuringDeathAnimation{ mIndex, "Game", "can loot during death animation" };
SettingValue<bool> mUseAdditionalAnimSources{ "Game", "use additional anim sources" }; SettingValue<bool> mRebalanceSoulGemValues{ mIndex, "Game", "rebalance soul gem values" };
SettingValue<bool> mBarterDispositionChangeIsPermanent{ "Game", "barter disposition change is permanent" }; SettingValue<bool> mUseAdditionalAnimSources{ mIndex, "Game", "use additional anim sources" };
SettingValue<int> mStrengthInfluencesHandToHand{ "Game", "strength influences hand to hand", SettingValue<bool> mBarterDispositionChangeIsPermanent{ mIndex, "Game",
"barter disposition change is permanent" };
SettingValue<int> mStrengthInfluencesHandToHand{ mIndex, "Game", "strength influences hand to hand",
makeEnumSanitizerInt({ 0, 1, 2 }) }; makeEnumSanitizerInt({ 0, 1, 2 }) };
SettingValue<bool> mWeaponSheathing{ "Game", "weapon sheathing" }; SettingValue<bool> mWeaponSheathing{ mIndex, "Game", "weapon sheathing" };
SettingValue<bool> mShieldSheathing{ "Game", "shield sheathing" }; SettingValue<bool> mShieldSheathing{ mIndex, "Game", "shield sheathing" };
SettingValue<bool> mOnlyAppropriateAmmunitionBypassesResistance{ "Game", SettingValue<bool> mOnlyAppropriateAmmunitionBypassesResistance{ mIndex, "Game",
"only appropriate ammunition bypasses resistance" }; "only appropriate ammunition bypasses resistance" };
SettingValue<bool> mUseMagicItemAnimations{ "Game", "use magic item animations" }; SettingValue<bool> mUseMagicItemAnimations{ mIndex, "Game", "use magic item animations" };
SettingValue<bool> mNormaliseRaceSpeed{ "Game", "normalise race speed" }; SettingValue<bool> mNormaliseRaceSpeed{ mIndex, "Game", "normalise race speed" };
SettingValue<float> mProjectilesEnchantMultiplier{ "Game", "projectiles enchant multiplier", SettingValue<float> mProjectilesEnchantMultiplier{ mIndex, "Game", "projectiles enchant multiplier",
makeClampSanitizerFloat(0, 1) }; makeClampSanitizerFloat(0, 1) };
SettingValue<bool> mUncappedDamageFatigue{ "Game", "uncapped damage fatigue" }; SettingValue<bool> mUncappedDamageFatigue{ mIndex, "Game", "uncapped damage fatigue" };
SettingValue<bool> mTurnToMovementDirection{ "Game", "turn to movement direction" }; SettingValue<bool> mTurnToMovementDirection{ mIndex, "Game", "turn to movement direction" };
SettingValue<bool> mSmoothMovement{ "Game", "smooth movement" }; SettingValue<bool> mSmoothMovement{ mIndex, "Game", "smooth movement" };
SettingValue<float> mSmoothMovementPlayerTurningDelay{ "Game", "smooth movement player turning delay", SettingValue<float> mSmoothMovementPlayerTurningDelay{ mIndex, "Game", "smooth movement player turning delay",
makeMaxSanitizerFloat(0.01f) }; makeMaxSanitizerFloat(0.01f) };
SettingValue<bool> mNPCsAvoidCollisions{ "Game", "NPCs avoid collisions" }; SettingValue<bool> mNPCsAvoidCollisions{ mIndex, "Game", "NPCs avoid collisions" };
SettingValue<bool> mNPCsGiveWay{ "Game", "NPCs give way" }; SettingValue<bool> mNPCsGiveWay{ mIndex, "Game", "NPCs give way" };
SettingValue<bool> mSwimUpwardCorrection{ "Game", "swim upward correction" }; SettingValue<bool> mSwimUpwardCorrection{ mIndex, "Game", "swim upward correction" };
SettingValue<float> mSwimUpwardCoef{ "Game", "swim upward coef", makeClampSanitizerFloat(-1, 1) }; SettingValue<float> mSwimUpwardCoef{ mIndex, "Game", "swim upward coef", makeClampSanitizerFloat(-1, 1) };
SettingValue<bool> mTrainersTrainingSkillsBasedOnBaseSkill{ "Game", SettingValue<bool> mTrainersTrainingSkillsBasedOnBaseSkill{ mIndex, "Game",
"trainers training skills based on base skill" }; "trainers training skills based on base skill" };
SettingValue<bool> mAlwaysAllowStealingFromKnockedOutActors{ "Game", SettingValue<bool> mAlwaysAllowStealingFromKnockedOutActors{ mIndex, "Game",
"always allow stealing from knocked out actors" }; "always allow stealing from knocked out actors" };
SettingValue<bool> mGraphicHerbalism{ "Game", "graphic herbalism" }; SettingValue<bool> mGraphicHerbalism{ mIndex, "Game", "graphic herbalism" };
SettingValue<bool> mAllowActorsToFollowOverWaterSurface{ "Game", "allow actors to follow over water surface" }; SettingValue<bool> mAllowActorsToFollowOverWaterSurface{ mIndex, "Game",
SettingValue<osg::Vec3f> mDefaultActorPathfindHalfExtents{ "Game", "default actor pathfind half extents", "allow actors to follow over water surface" };
makeMaxStrictSanitizerVec3f(osg::Vec3f(0, 0, 0)) }; SettingValue<osg::Vec3f> mDefaultActorPathfindHalfExtents{ mIndex, "Game",
SettingValue<bool> mDayNightSwitches{ "Game", "day night switches" }; "default actor pathfind half extents", makeMaxStrictSanitizerVec3f(osg::Vec3f(0, 0, 0)) };
SettingValue<bool> mUnarmedCreatureAttacksDamageArmor{ "Game", "unarmed creature attacks damage armor" }; SettingValue<bool> mDayNightSwitches{ mIndex, "Game", "day night switches" };
SettingValue<int> mActorCollisionShapeType{ "Game", "actor collision shape type", SettingValue<bool> mUnarmedCreatureAttacksDamageArmor{ mIndex, "Game",
"unarmed creature attacks damage armor" };
SettingValue<int> mActorCollisionShapeType{ mIndex, "Game", "actor collision shape type",
makeEnumSanitizerInt({ 0, 1, 2 }) }; makeEnumSanitizerInt({ 0, 1, 2 }) };
}; };
} }

@ -14,21 +14,23 @@
namespace Settings namespace Settings
{ {
struct GeneralCategory struct GeneralCategory : WithIndex
{ {
SettingValue<int> mAnisotropy{ "General", "anisotropy", makeClampSanitizerInt(0, 16) }; using WithIndex::WithIndex;
SettingValue<std::string> mScreenshotFormat{ "General", "screenshot format",
SettingValue<int> mAnisotropy{ mIndex, "General", "anisotropy", makeClampSanitizerInt(0, 16) };
SettingValue<std::string> mScreenshotFormat{ mIndex, "General", "screenshot format",
makeEnumSanitizerString({ "jpg", "png", "tga" }) }; makeEnumSanitizerString({ "jpg", "png", "tga" }) };
SettingValue<std::string> mTextureMagFilter{ "General", "texture mag filter", SettingValue<std::string> mTextureMagFilter{ mIndex, "General", "texture mag filter",
makeEnumSanitizerString({ "nearest", "linear" }) }; makeEnumSanitizerString({ "nearest", "linear" }) };
SettingValue<std::string> mTextureMinFilter{ "General", "texture min filter", SettingValue<std::string> mTextureMinFilter{ mIndex, "General", "texture min filter",
makeEnumSanitizerString({ "nearest", "linear" }) }; makeEnumSanitizerString({ "nearest", "linear" }) };
SettingValue<std::string> mTextureMipmap{ "General", "texture mipmap", SettingValue<std::string> mTextureMipmap{ mIndex, "General", "texture mipmap",
makeEnumSanitizerString({ "none", "nearest", "linear" }) }; makeEnumSanitizerString({ "none", "nearest", "linear" }) };
SettingValue<bool> mNotifyOnSavedScreenshot{ "General", "notify on saved screenshot" }; SettingValue<bool> mNotifyOnSavedScreenshot{ mIndex, "General", "notify on saved screenshot" };
SettingValue<std::string> mPreferredLocales{ "General", "preferred locales" }; SettingValue<std::string> mPreferredLocales{ mIndex, "General", "preferred locales" };
SettingValue<std::size_t> mLogBufferSize{ "General", "log buffer size" }; SettingValue<std::size_t> mLogBufferSize{ mIndex, "General", "log buffer size" };
SettingValue<std::size_t> mConsoleHistoryBufferSize{ "General", "console history buffer size" }; SettingValue<std::size_t> mConsoleHistoryBufferSize{ mIndex, "General", "console history buffer size" };
}; };
} }

@ -14,13 +14,16 @@
namespace Settings namespace Settings
{ {
struct GroundcoverCategory struct GroundcoverCategory : WithIndex
{ {
SettingValue<bool> mEnabled{ "Groundcover", "enabled" }; using WithIndex::WithIndex;
SettingValue<float> mDensity{ "Groundcover", "density", makeClampSanitizerFloat(0, 1) };
SettingValue<float> mRenderingDistance{ "Groundcover", "rendering distance", makeMaxSanitizerFloat(0) }; SettingValue<bool> mEnabled{ mIndex, "Groundcover", "enabled" };
SettingValue<int> mStompMode{ "Groundcover", "stomp mode", makeEnumSanitizerInt({ 0, 1, 2 }) }; SettingValue<float> mDensity{ mIndex, "Groundcover", "density", makeClampSanitizerFloat(0, 1) };
SettingValue<int> mStompIntensity{ "Groundcover", "stomp intensity", makeEnumSanitizerInt({ 0, 1, 2 }) }; SettingValue<float> mRenderingDistance{ mIndex, "Groundcover", "rendering distance", makeMaxSanitizerFloat(0) };
SettingValue<int> mStompMode{ mIndex, "Groundcover", "stomp mode", makeEnumSanitizerInt({ 0, 1, 2 }) };
SettingValue<int> mStompIntensity{ mIndex, "Groundcover", "stomp intensity",
makeEnumSanitizerInt({ 0, 1, 2 }) };
}; };
} }

@ -14,22 +14,27 @@
namespace Settings namespace Settings
{ {
struct GUICategory struct GUICategory : WithIndex
{ {
SettingValue<float> mScalingFactor{ "GUI", "scaling factor", makeClampSanitizerFloat(0.5f, 8) }; using WithIndex::WithIndex;
SettingValue<int> mFontSize{ "GUI", "font size", makeClampSanitizerInt(12, 18) };
SettingValue<float> mMenuTransparency{ "GUI", "menu transparency", makeClampSanitizerFloat(0, 1) }; SettingValue<float> mScalingFactor{ mIndex, "GUI", "scaling factor", makeClampSanitizerFloat(0.5f, 8) };
SettingValue<float> mTooltipDelay{ "GUI", "tooltip delay", makeMaxSanitizerFloat(0) }; SettingValue<int> mFontSize{ mIndex, "GUI", "font size", makeClampSanitizerInt(12, 18) };
SettingValue<bool> mStretchMenuBackground{ "GUI", "stretch menu background" }; SettingValue<float> mMenuTransparency{ mIndex, "GUI", "menu transparency", makeClampSanitizerFloat(0, 1) };
SettingValue<bool> mSubtitles{ "GUI", "subtitles" }; SettingValue<float> mTooltipDelay{ mIndex, "GUI", "tooltip delay", makeMaxSanitizerFloat(0) };
SettingValue<bool> mHitFader{ "GUI", "hit fader" }; SettingValue<bool> mStretchMenuBackground{ mIndex, "GUI", "stretch menu background" };
SettingValue<bool> mWerewolfOverlay{ "GUI", "werewolf overlay" }; SettingValue<bool> mSubtitles{ mIndex, "GUI", "subtitles" };
SettingValue<float> mColorBackgroundOwned{ "GUI", "color background owned", makeClampSanitizerFloat(0, 1) }; SettingValue<bool> mHitFader{ mIndex, "GUI", "hit fader" };
SettingValue<float> mColorCrosshairOwned{ "GUI", "color crosshair owned", makeClampSanitizerFloat(0, 1) }; SettingValue<bool> mWerewolfOverlay{ mIndex, "GUI", "werewolf overlay" };
SettingValue<bool> mKeyboardNavigation{ "GUI", "keyboard navigation" }; SettingValue<float> mColorBackgroundOwned{ mIndex, "GUI", "color background owned",
SettingValue<bool> mColorTopicEnable{ "GUI", "color topic enable" }; makeClampSanitizerFloat(0, 1) };
SettingValue<float> mColorTopicSpecific{ "GUI", "color topic specific", makeClampSanitizerFloat(0, 1) }; SettingValue<float> mColorCrosshairOwned{ mIndex, "GUI", "color crosshair owned",
SettingValue<float> mColorTopicExhausted{ "GUI", "color topic exhausted", makeClampSanitizerFloat(0, 1) }; makeClampSanitizerFloat(0, 1) };
SettingValue<bool> mKeyboardNavigation{ mIndex, "GUI", "keyboard navigation" };
SettingValue<bool> mColorTopicEnable{ mIndex, "GUI", "color topic enable" };
SettingValue<float> mColorTopicSpecific{ mIndex, "GUI", "color topic specific", makeClampSanitizerFloat(0, 1) };
SettingValue<float> mColorTopicExhausted{ mIndex, "GUI", "color topic exhausted",
makeClampSanitizerFloat(0, 1) };
}; };
} }

@ -14,9 +14,11 @@
namespace Settings namespace Settings
{ {
struct HUDCategory struct HUDCategory : WithIndex
{ {
SettingValue<bool> mCrosshair{ "HUD", "crosshair" }; using WithIndex::WithIndex;
SettingValue<bool> mCrosshair{ mIndex, "HUD", "crosshair" };
}; };
} }

@ -14,25 +14,30 @@
namespace Settings namespace Settings
{ {
struct InputCategory struct InputCategory : WithIndex
{ {
SettingValue<bool> mGrabCursor{ "Input", "grab cursor" }; using WithIndex::WithIndex;
SettingValue<float> mCameraSensitivity{ "Input", "camera sensitivity", makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mCameraYMultiplier{ "Input", "camera y multiplier", makeMaxStrictSanitizerFloat(0) }; SettingValue<bool> mGrabCursor{ mIndex, "Input", "grab cursor" };
SettingValue<bool> mInvertXAxis{ "Input", "invert x axis" }; SettingValue<float> mCameraSensitivity{ mIndex, "Input", "camera sensitivity", makeMaxStrictSanitizerFloat(0) };
SettingValue<bool> mInvertYAxis{ "Input", "invert y axis" }; SettingValue<float> mCameraYMultiplier{ mIndex, "Input", "camera y multiplier",
SettingValue<bool> mEnableController{ "Input", "enable controller" }; makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mGamepadCursorSpeed{ "Input", "gamepad cursor speed", makeMaxStrictSanitizerFloat(0) }; SettingValue<bool> mInvertXAxis{ mIndex, "Input", "invert x axis" };
SettingValue<float> mJoystickDeadZone{ "Input", "joystick dead zone", makeClampSanitizerFloat(0, 0.5f) }; SettingValue<bool> mInvertYAxis{ mIndex, "Input", "invert y axis" };
SettingValue<bool> mEnableGyroscope{ "Input", "enable gyroscope" }; SettingValue<bool> mEnableController{ mIndex, "Input", "enable controller" };
SettingValue<std::string> mGyroHorizontalAxis{ "Input", "gyro horizontal axis", SettingValue<float> mGamepadCursorSpeed{ mIndex, "Input", "gamepad cursor speed",
makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mJoystickDeadZone{ mIndex, "Input", "joystick dead zone",
makeClampSanitizerFloat(0, 0.5f) };
SettingValue<bool> mEnableGyroscope{ mIndex, "Input", "enable gyroscope" };
SettingValue<std::string> mGyroHorizontalAxis{ mIndex, "Input", "gyro horizontal axis",
makeEnumSanitizerString({ "x", "y", "z", "-x", "-y", "-z" }) }; makeEnumSanitizerString({ "x", "y", "z", "-x", "-y", "-z" }) };
SettingValue<std::string> mGyroVerticalAxis{ "Input", "gyro vertical axis", SettingValue<std::string> mGyroVerticalAxis{ mIndex, "Input", "gyro vertical axis",
makeEnumSanitizerString({ "x", "y", "z", "-x", "-y", "-z" }) }; makeEnumSanitizerString({ "x", "y", "z", "-x", "-y", "-z" }) };
SettingValue<float> mGyroInputThreshold{ "Input", "gyro input threshold", makeMaxSanitizerFloat(0) }; SettingValue<float> mGyroInputThreshold{ mIndex, "Input", "gyro input threshold", makeMaxSanitizerFloat(0) };
SettingValue<float> mGyroHorizontalSensitivity{ "Input", "gyro horizontal sensitivity", SettingValue<float> mGyroHorizontalSensitivity{ mIndex, "Input", "gyro horizontal sensitivity",
makeMaxStrictSanitizerFloat(0) }; makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mGyroVerticalSensitivity{ "Input", "gyro vertical sensitivity", SettingValue<float> mGyroVerticalSensitivity{ mIndex, "Input", "gyro vertical sensitivity",
makeMaxStrictSanitizerFloat(0) }; makeMaxStrictSanitizerFloat(0) };
}; };
} }

@ -14,17 +14,19 @@
namespace Settings namespace Settings
{ {
struct LuaCategory struct LuaCategory : WithIndex
{ {
SettingValue<bool> mLuaDebug{ "Lua", "lua debug" }; using WithIndex::WithIndex;
SettingValue<int> mLuaNumThreads{ "Lua", "lua num threads", makeEnumSanitizerInt({ 0, 1 }) };
SettingValue<bool> mLuaProfiler{ "Lua", "lua profiler" }; SettingValue<bool> mLuaDebug{ mIndex, "Lua", "lua debug" };
SettingValue<std::uint64_t> mSmallAllocMaxSize{ "Lua", "small alloc max size" }; SettingValue<int> mLuaNumThreads{ mIndex, "Lua", "lua num threads", makeEnumSanitizerInt({ 0, 1 }) };
SettingValue<std::uint64_t> mMemoryLimit{ "Lua", "memory limit" }; SettingValue<bool> mLuaProfiler{ mIndex, "Lua", "lua profiler" };
SettingValue<bool> mLogMemoryUsage{ "Lua", "log memory usage" }; SettingValue<std::uint64_t> mSmallAllocMaxSize{ mIndex, "Lua", "small alloc max size" };
SettingValue<std::uint64_t> mInstructionLimitPerCall{ "Lua", "instruction limit per call", SettingValue<std::uint64_t> mMemoryLimit{ mIndex, "Lua", "memory limit" };
SettingValue<bool> mLogMemoryUsage{ mIndex, "Lua", "log memory usage" };
SettingValue<std::uint64_t> mInstructionLimitPerCall{ mIndex, "Lua", "instruction limit per call",
makeMaxSanitizerUInt64(1001) }; makeMaxSanitizerUInt64(1001) };
SettingValue<int> mGcStepsPerFrame{ "Lua", "gc steps per frame", makeMaxSanitizerInt(0) }; SettingValue<int> mGcStepsPerFrame{ mIndex, "Lua", "gc steps per frame", makeMaxSanitizerInt(0) };
}; };
} }

@ -14,16 +14,19 @@
namespace Settings namespace Settings
{ {
struct MapCategory struct MapCategory : WithIndex
{ {
SettingValue<int> mGlobalMapCellSize{ "Map", "global map cell size", makeMaxSanitizerInt(1) }; using WithIndex::WithIndex;
SettingValue<int> mLocalMapHudWidgetSize{ "Map", "local map hud widget size", makeMaxSanitizerInt(1) };
SettingValue<bool> mLocalMapHudFogOfWar{ "Map", "local map hud fog of war" }; SettingValue<int> mGlobalMapCellSize{ mIndex, "Map", "global map cell size", makeMaxSanitizerInt(1) };
SettingValue<int> mLocalMapResolution{ "Map", "local map resolution", makeMaxSanitizerInt(1) }; SettingValue<int> mLocalMapHudWidgetSize{ mIndex, "Map", "local map hud widget size", makeMaxSanitizerInt(1) };
SettingValue<int> mLocalMapWidgetSize{ "Map", "local map widget size", makeMaxSanitizerInt(1) }; SettingValue<bool> mLocalMapHudFogOfWar{ mIndex, "Map", "local map hud fog of war" };
SettingValue<bool> mGlobal{ "Map", "global" }; SettingValue<int> mLocalMapResolution{ mIndex, "Map", "local map resolution", makeMaxSanitizerInt(1) };
SettingValue<bool> mAllowZooming{ "Map", "allow zooming" }; SettingValue<int> mLocalMapWidgetSize{ mIndex, "Map", "local map widget size", makeMaxSanitizerInt(1) };
SettingValue<int> mMaxLocalViewingDistance{ "Map", "max local viewing distance", makeMaxSanitizerInt(1) }; SettingValue<bool> mGlobal{ mIndex, "Map", "global" };
SettingValue<bool> mAllowZooming{ mIndex, "Map", "allow zooming" };
SettingValue<int> mMaxLocalViewingDistance{ mIndex, "Map", "max local viewing distance",
makeMaxSanitizerInt(1) };
}; };
} }

@ -14,33 +14,35 @@
namespace Settings namespace Settings
{ {
struct ModelsCategory struct ModelsCategory : WithIndex
{ {
SettingValue<bool> mLoadUnsupportedNifFiles{ "Models", "load unsupported nif files" }; using WithIndex::WithIndex;
SettingValue<std::string> mXbaseanim{ "Models", "xbaseanim" };
SettingValue<std::string> mBaseanim{ "Models", "baseanim" }; SettingValue<bool> mLoadUnsupportedNifFiles{ mIndex, "Models", "load unsupported nif files" };
SettingValue<std::string> mXbaseanim1st{ "Models", "xbaseanim1st" }; SettingValue<std::string> mXbaseanim{ mIndex, "Models", "xbaseanim" };
SettingValue<std::string> mBaseanimkna{ "Models", "baseanimkna" }; SettingValue<std::string> mBaseanim{ mIndex, "Models", "baseanim" };
SettingValue<std::string> mBaseanimkna1st{ "Models", "baseanimkna1st" }; SettingValue<std::string> mXbaseanim1st{ mIndex, "Models", "xbaseanim1st" };
SettingValue<std::string> mXbaseanimfemale{ "Models", "xbaseanimfemale" }; SettingValue<std::string> mBaseanimkna{ mIndex, "Models", "baseanimkna" };
SettingValue<std::string> mBaseanimfemale{ "Models", "baseanimfemale" }; SettingValue<std::string> mBaseanimkna1st{ mIndex, "Models", "baseanimkna1st" };
SettingValue<std::string> mBaseanimfemale1st{ "Models", "baseanimfemale1st" }; SettingValue<std::string> mXbaseanimfemale{ mIndex, "Models", "xbaseanimfemale" };
SettingValue<std::string> mWolfskin{ "Models", "wolfskin" }; SettingValue<std::string> mBaseanimfemale{ mIndex, "Models", "baseanimfemale" };
SettingValue<std::string> mWolfskin1st{ "Models", "wolfskin1st" }; SettingValue<std::string> mBaseanimfemale1st{ mIndex, "Models", "baseanimfemale1st" };
SettingValue<std::string> mXargonianswimkna{ "Models", "xargonianswimkna" }; SettingValue<std::string> mWolfskin{ mIndex, "Models", "wolfskin" };
SettingValue<std::string> mXbaseanimkf{ "Models", "xbaseanimkf" }; SettingValue<std::string> mWolfskin1st{ mIndex, "Models", "wolfskin1st" };
SettingValue<std::string> mXbaseanim1stkf{ "Models", "xbaseanim1stkf" }; SettingValue<std::string> mXargonianswimkna{ mIndex, "Models", "xargonianswimkna" };
SettingValue<std::string> mXbaseanimfemalekf{ "Models", "xbaseanimfemalekf" }; SettingValue<std::string> mXbaseanimkf{ mIndex, "Models", "xbaseanimkf" };
SettingValue<std::string> mXargonianswimknakf{ "Models", "xargonianswimknakf" }; SettingValue<std::string> mXbaseanim1stkf{ mIndex, "Models", "xbaseanim1stkf" };
SettingValue<std::string> mSkyatmosphere{ "Models", "skyatmosphere" }; SettingValue<std::string> mXbaseanimfemalekf{ mIndex, "Models", "xbaseanimfemalekf" };
SettingValue<std::string> mSkyclouds{ "Models", "skyclouds" }; SettingValue<std::string> mXargonianswimknakf{ mIndex, "Models", "xargonianswimknakf" };
SettingValue<std::string> mSkynight01{ "Models", "skynight01" }; SettingValue<std::string> mSkyatmosphere{ mIndex, "Models", "skyatmosphere" };
SettingValue<std::string> mSkynight02{ "Models", "skynight02" }; SettingValue<std::string> mSkyclouds{ mIndex, "Models", "skyclouds" };
SettingValue<std::string> mWeatherashcloud{ "Models", "weatherashcloud" }; SettingValue<std::string> mSkynight01{ mIndex, "Models", "skynight01" };
SettingValue<std::string> mWeatherblightcloud{ "Models", "weatherblightcloud" }; SettingValue<std::string> mSkynight02{ mIndex, "Models", "skynight02" };
SettingValue<std::string> mWeathersnow{ "Models", "weathersnow" }; SettingValue<std::string> mWeatherashcloud{ mIndex, "Models", "weatherashcloud" };
SettingValue<std::string> mWeatherblizzard{ "Models", "weatherblizzard" }; SettingValue<std::string> mWeatherblightcloud{ mIndex, "Models", "weatherblightcloud" };
SettingValue<bool> mWriteNifDebugLog{ "Models", "write nif debug log" }; SettingValue<std::string> mWeathersnow{ mIndex, "Models", "weathersnow" };
SettingValue<std::string> mWeatherblizzard{ mIndex, "Models", "weatherblizzard" };
SettingValue<bool> mWriteNifDebugLog{ mIndex, "Models", "write nif debug log" };
}; };
} }

@ -14,50 +14,55 @@
namespace Settings namespace Settings
{ {
struct NavigatorCategory struct NavigatorCategory : WithIndex
{ {
SettingValue<bool> mEnable{ "Navigator", "enable" }; using WithIndex::WithIndex;
SettingValue<float> mRecastScaleFactor{ "Navigator", "recast scale factor", makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mCellHeight{ "Navigator", "cell height", makeMaxStrictSanitizerFloat(0) }; SettingValue<bool> mEnable{ mIndex, "Navigator", "enable" };
SettingValue<float> mCellSize{ "Navigator", "cell size", makeMaxStrictSanitizerFloat(0) }; SettingValue<float> mRecastScaleFactor{ mIndex, "Navigator", "recast scale factor",
SettingValue<float> mDetailSampleDist{ "Navigator", "detail sample dist", makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mCellHeight{ mIndex, "Navigator", "cell height", makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mCellSize{ mIndex, "Navigator", "cell size", makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mDetailSampleDist{ mIndex, "Navigator", "detail sample dist",
makeEqualOrMaxSanitizerFloat(0, 0.9f) }; makeEqualOrMaxSanitizerFloat(0, 0.9f) };
SettingValue<float> mDetailSampleMaxError{ "Navigator", "detail sample max error", makeMaxSanitizerFloat(0) }; SettingValue<float> mDetailSampleMaxError{ mIndex, "Navigator", "detail sample max error",
SettingValue<float> mMaxSimplificationError{ "Navigator", "max simplification error", makeMaxSanitizerFloat(0) };
SettingValue<float> mMaxSimplificationError{ mIndex, "Navigator", "max simplification error",
makeMaxSanitizerFloat(0) }; makeMaxSanitizerFloat(0) };
SettingValue<int> mTileSize{ "Navigator", "tile size", makeMaxSanitizerInt(1) }; SettingValue<int> mTileSize{ mIndex, "Navigator", "tile size", makeMaxSanitizerInt(1) };
SettingValue<int> mBorderSize{ "Navigator", "border size", makeMaxSanitizerInt(0) }; SettingValue<int> mBorderSize{ mIndex, "Navigator", "border size", makeMaxSanitizerInt(0) };
SettingValue<int> mMaxEdgeLen{ "Navigator", "max edge len", makeMaxSanitizerInt(0) }; SettingValue<int> mMaxEdgeLen{ mIndex, "Navigator", "max edge len", makeMaxSanitizerInt(0) };
SettingValue<int> mMaxNavMeshQueryNodes{ "Navigator", "max nav mesh query nodes", SettingValue<int> mMaxNavMeshQueryNodes{ mIndex, "Navigator", "max nav mesh query nodes",
makeClampSanitizerInt(1, 65535) }; makeClampSanitizerInt(1, 65535) };
SettingValue<int> mMaxPolygonsPerTile{ "Navigator", "max polygons per tile", SettingValue<int> mMaxPolygonsPerTile{ mIndex, "Navigator", "max polygons per tile",
makeClampSanitizerInt(1, 1 << 21) }; makeClampSanitizerInt(1, 1 << 21) };
SettingValue<int> mMaxVertsPerPoly{ "Navigator", "max verts per poly", makeMaxSanitizerInt(3) }; SettingValue<int> mMaxVertsPerPoly{ mIndex, "Navigator", "max verts per poly", makeMaxSanitizerInt(3) };
SettingValue<int> mRegionMergeArea{ "Navigator", "region merge area", makeMaxSanitizerInt(0) }; SettingValue<int> mRegionMergeArea{ mIndex, "Navigator", "region merge area", makeMaxSanitizerInt(0) };
SettingValue<int> mRegionMinArea{ "Navigator", "region min area", makeMaxSanitizerInt(0) }; SettingValue<int> mRegionMinArea{ mIndex, "Navigator", "region min area", makeMaxSanitizerInt(0) };
SettingValue<std::size_t> mAsyncNavMeshUpdaterThreads{ "Navigator", "async nav mesh updater threads", SettingValue<std::size_t> mAsyncNavMeshUpdaterThreads{ mIndex, "Navigator", "async nav mesh updater threads",
makeMaxSanitizerSize(1) }; makeMaxSanitizerSize(1) };
SettingValue<std::size_t> mMaxNavMeshTilesCacheSize{ "Navigator", "max nav mesh tiles cache size" }; SettingValue<std::size_t> mMaxNavMeshTilesCacheSize{ mIndex, "Navigator", "max nav mesh tiles cache size" };
SettingValue<std::size_t> mMaxPolygonPathSize{ "Navigator", "max polygon path size" }; SettingValue<std::size_t> mMaxPolygonPathSize{ mIndex, "Navigator", "max polygon path size" };
SettingValue<std::size_t> mMaxSmoothPathSize{ "Navigator", "max smooth path size" }; SettingValue<std::size_t> mMaxSmoothPathSize{ mIndex, "Navigator", "max smooth path size" };
SettingValue<bool> mEnableWriteRecastMeshToFile{ "Navigator", "enable write recast mesh to file" }; SettingValue<bool> mEnableWriteRecastMeshToFile{ mIndex, "Navigator", "enable write recast mesh to file" };
SettingValue<bool> mEnableWriteNavMeshToFile{ "Navigator", "enable write nav mesh to file" }; SettingValue<bool> mEnableWriteNavMeshToFile{ mIndex, "Navigator", "enable write nav mesh to file" };
SettingValue<bool> mEnableRecastMeshFileNameRevision{ "Navigator", "enable recast mesh file name revision" }; SettingValue<bool> mEnableRecastMeshFileNameRevision{ mIndex, "Navigator",
SettingValue<bool> mEnableNavMeshFileNameRevision{ "Navigator", "enable nav mesh file name revision" }; "enable recast mesh file name revision" };
SettingValue<std::string> mRecastMeshPathPrefix{ "Navigator", "recast mesh path prefix" }; SettingValue<bool> mEnableNavMeshFileNameRevision{ mIndex, "Navigator", "enable nav mesh file name revision" };
SettingValue<std::string> mNavMeshPathPrefix{ "Navigator", "nav mesh path prefix" }; SettingValue<std::string> mRecastMeshPathPrefix{ mIndex, "Navigator", "recast mesh path prefix" };
SettingValue<bool> mEnableNavMeshRender{ "Navigator", "enable nav mesh render" }; SettingValue<std::string> mNavMeshPathPrefix{ mIndex, "Navigator", "nav mesh path prefix" };
SettingValue<std::string> mNavMeshRenderMode{ "Navigator", "nav mesh render mode", SettingValue<bool> mEnableNavMeshRender{ mIndex, "Navigator", "enable nav mesh render" };
SettingValue<std::string> mNavMeshRenderMode{ mIndex, "Navigator", "nav mesh render mode",
makeEnumSanitizerString({ "area type", "update frequency" }) }; makeEnumSanitizerString({ "area type", "update frequency" }) };
SettingValue<bool> mEnableAgentsPathsRender{ "Navigator", "enable agents paths render" }; SettingValue<bool> mEnableAgentsPathsRender{ mIndex, "Navigator", "enable agents paths render" };
SettingValue<bool> mEnableRecastMeshRender{ "Navigator", "enable recast mesh render" }; SettingValue<bool> mEnableRecastMeshRender{ mIndex, "Navigator", "enable recast mesh render" };
SettingValue<int> mMaxTilesNumber{ "Navigator", "max tiles number", makeMaxSanitizerInt(0) }; SettingValue<int> mMaxTilesNumber{ mIndex, "Navigator", "max tiles number", makeMaxSanitizerInt(0) };
SettingValue<int> mMinUpdateIntervalMs{ "Navigator", "min update interval ms", makeMaxSanitizerInt(0) }; SettingValue<int> mMinUpdateIntervalMs{ mIndex, "Navigator", "min update interval ms", makeMaxSanitizerInt(0) };
SettingValue<int> mWaitUntilMinDistanceToPlayer{ "Navigator", "wait until min distance to player", SettingValue<int> mWaitUntilMinDistanceToPlayer{ mIndex, "Navigator", "wait until min distance to player",
makeMaxSanitizerInt(0) }; makeMaxSanitizerInt(0) };
SettingValue<bool> mEnableNavMeshDiskCache{ "Navigator", "enable nav mesh disk cache" }; SettingValue<bool> mEnableNavMeshDiskCache{ mIndex, "Navigator", "enable nav mesh disk cache" };
SettingValue<bool> mWriteToNavmeshdb{ "Navigator", "write to navmeshdb" }; SettingValue<bool> mWriteToNavmeshdb{ mIndex, "Navigator", "write to navmeshdb" };
SettingValue<std::uint64_t> mMaxNavmeshdbFileSize{ "Navigator", "max navmeshdb file size" }; SettingValue<std::uint64_t> mMaxNavmeshdbFileSize{ mIndex, "Navigator", "max navmeshdb file size" };
}; };
} }

@ -14,10 +14,12 @@
namespace Settings namespace Settings
{ {
struct PhysicsCategory struct PhysicsCategory : WithIndex
{ {
SettingValue<int> mAsyncNumThreads{ "Physics", "async num threads", makeMaxSanitizerInt(0) }; using WithIndex::WithIndex;
SettingValue<int> mLineofsightKeepInactiveCache{ "Physics", "lineofsight keep inactive cache",
SettingValue<int> mAsyncNumThreads{ mIndex, "Physics", "async num threads", makeMaxSanitizerInt(0) };
SettingValue<int> mLineofsightKeepInactiveCache{ mIndex, "Physics", "lineofsight keep inactive cache",
makeMaxSanitizerInt(-1) }; makeMaxSanitizerInt(-1) };
}; };
} }

@ -14,13 +14,15 @@
namespace Settings namespace Settings
{ {
struct PostProcessingCategory struct PostProcessingCategory : WithIndex
{ {
SettingValue<bool> mEnabled{ "Post Processing", "enabled" }; using WithIndex::WithIndex;
SettingValue<std::string> mChain{ "Post Processing", "chain" };
SettingValue<float> mAutoExposureSpeed{ "Post Processing", "auto exposure speed", SettingValue<bool> mEnabled{ mIndex, "Post Processing", "enabled" };
SettingValue<std::string> mChain{ mIndex, "Post Processing", "chain" };
SettingValue<float> mAutoExposureSpeed{ mIndex, "Post Processing", "auto exposure speed",
makeMaxStrictSanitizerFloat(0.0001f) }; makeMaxStrictSanitizerFloat(0.0001f) };
SettingValue<bool> mTransparentPostpass{ "Post Processing", "transparent postpass" }; SettingValue<bool> mTransparentPostpass{ mIndex, "Post Processing", "transparent postpass" };
}; };
} }

@ -14,12 +14,14 @@
namespace Settings namespace Settings
{ {
struct SavesCategory struct SavesCategory : WithIndex
{ {
SettingValue<std::string> mCharacter{ "Saves", "character" }; using WithIndex::WithIndex;
SettingValue<bool> mAutosave{ "Saves", "autosave" };
SettingValue<bool> mTimeplayed{ "Saves", "timeplayed" }; SettingValue<std::string> mCharacter{ mIndex, "Saves", "character" };
SettingValue<int> mMaxQuicksaves{ "Saves", "max quicksaves", makeMaxSanitizerInt(1) }; SettingValue<bool> mAutosave{ mIndex, "Saves", "autosave" };
SettingValue<bool> mTimeplayed{ mIndex, "Saves", "timeplayed" };
SettingValue<int> mMaxQuicksaves{ mIndex, "Saves", "max quicksaves", makeMaxSanitizerInt(1) };
}; };
} }

@ -14,34 +14,36 @@
namespace Settings namespace Settings
{ {
struct ShadersCategory struct ShadersCategory : WithIndex
{ {
SettingValue<bool> mForceShaders{ "Shaders", "force shaders" }; using WithIndex::WithIndex;
SettingValue<bool> mForcePerPixelLighting{ "Shaders", "force per pixel lighting" };
SettingValue<bool> mClampLighting{ "Shaders", "clamp lighting" }; SettingValue<bool> mForceShaders{ mIndex, "Shaders", "force shaders" };
SettingValue<bool> mAutoUseObjectNormalMaps{ "Shaders", "auto use object normal maps" }; SettingValue<bool> mForcePerPixelLighting{ mIndex, "Shaders", "force per pixel lighting" };
SettingValue<bool> mAutoUseObjectSpecularMaps{ "Shaders", "auto use object specular maps" }; SettingValue<bool> mClampLighting{ mIndex, "Shaders", "clamp lighting" };
SettingValue<bool> mAutoUseTerrainNormalMaps{ "Shaders", "auto use terrain normal maps" }; SettingValue<bool> mAutoUseObjectNormalMaps{ mIndex, "Shaders", "auto use object normal maps" };
SettingValue<bool> mAutoUseTerrainSpecularMaps{ "Shaders", "auto use terrain specular maps" }; SettingValue<bool> mAutoUseObjectSpecularMaps{ mIndex, "Shaders", "auto use object specular maps" };
SettingValue<std::string> mNormalMapPattern{ "Shaders", "normal map pattern" }; SettingValue<bool> mAutoUseTerrainNormalMaps{ mIndex, "Shaders", "auto use terrain normal maps" };
SettingValue<std::string> mNormalHeightMapPattern{ "Shaders", "normal height map pattern" }; SettingValue<bool> mAutoUseTerrainSpecularMaps{ mIndex, "Shaders", "auto use terrain specular maps" };
SettingValue<std::string> mSpecularMapPattern{ "Shaders", "specular map pattern" }; SettingValue<std::string> mNormalMapPattern{ mIndex, "Shaders", "normal map pattern" };
SettingValue<std::string> mTerrainSpecularMapPattern{ "Shaders", "terrain specular map pattern" }; SettingValue<std::string> mNormalHeightMapPattern{ mIndex, "Shaders", "normal height map pattern" };
SettingValue<bool> mApplyLightingToEnvironmentMaps{ "Shaders", "apply lighting to environment maps" }; SettingValue<std::string> mSpecularMapPattern{ mIndex, "Shaders", "specular map pattern" };
SettingValue<std::string> mLightingMethod{ "Shaders", "lighting method", SettingValue<std::string> mTerrainSpecularMapPattern{ mIndex, "Shaders", "terrain specular map pattern" };
SettingValue<bool> mApplyLightingToEnvironmentMaps{ mIndex, "Shaders", "apply lighting to environment maps" };
SettingValue<std::string> mLightingMethod{ mIndex, "Shaders", "lighting method",
makeEnumSanitizerString({ "legacy", "shaders compatibility", "shaders" }) }; makeEnumSanitizerString({ "legacy", "shaders compatibility", "shaders" }) };
SettingValue<float> mLightBoundsMultiplier{ "Shaders", "light bounds multiplier", SettingValue<float> mLightBoundsMultiplier{ mIndex, "Shaders", "light bounds multiplier",
makeClampSanitizerFloat(0, 5) }; makeClampSanitizerFloat(0, 5) };
SettingValue<float> mMaximumLightDistance{ "Shaders", "maximum light distance" }; SettingValue<float> mMaximumLightDistance{ mIndex, "Shaders", "maximum light distance" };
SettingValue<float> mLightFadeStart{ "Shaders", "light fade start", makeClampSanitizerFloat(0, 1) }; SettingValue<float> mLightFadeStart{ mIndex, "Shaders", "light fade start", makeClampSanitizerFloat(0, 1) };
SettingValue<int> mMaxLights{ "Shaders", "max lights", makeClampSanitizerInt(2, 64) }; SettingValue<int> mMaxLights{ mIndex, "Shaders", "max lights", makeClampSanitizerInt(2, 64) };
SettingValue<float> mMinimumInteriorBrightness{ "Shaders", "minimum interior brightness", SettingValue<float> mMinimumInteriorBrightness{ mIndex, "Shaders", "minimum interior brightness",
makeClampSanitizerFloat(0, 1) }; makeClampSanitizerFloat(0, 1) };
SettingValue<bool> mAntialiasAlphaTest{ "Shaders", "antialias alpha test" }; SettingValue<bool> mAntialiasAlphaTest{ mIndex, "Shaders", "antialias alpha test" };
SettingValue<bool> mAdjustCoverageForAlphaTest{ "Shaders", "adjust coverage for alpha test" }; SettingValue<bool> mAdjustCoverageForAlphaTest{ mIndex, "Shaders", "adjust coverage for alpha test" };
SettingValue<bool> mSoftParticles{ "Shaders", "soft particles" }; SettingValue<bool> mSoftParticles{ mIndex, "Shaders", "soft particles" };
SettingValue<bool> mWeatherParticleOcclusion{ "Shaders", "weather particle occlusion" }; SettingValue<bool> mWeatherParticleOcclusion{ mIndex, "Shaders", "weather particle occlusion" };
SettingValue<float> mWeatherParticleOcclusionSmallFeatureCullingPixelSize{ "Shaders", SettingValue<float> mWeatherParticleOcclusionSmallFeatureCullingPixelSize{ mIndex, "Shaders",
"weather particle occlusion small feature culling pixel size" }; "weather particle occlusion small feature culling pixel size" };
}; };
} }

@ -14,32 +14,35 @@
namespace Settings namespace Settings
{ {
struct ShadowsCategory struct ShadowsCategory : WithIndex
{ {
SettingValue<bool> mEnableShadows{ "Shadows", "enable shadows" }; using WithIndex::WithIndex;
SettingValue<int> mNumberOfShadowMaps{ "Shadows", "number of shadow maps", makeClampSanitizerInt(1, 8) };
SettingValue<float> mMaximumShadowMapDistance{ "Shadows", "maximum shadow map distance" }; SettingValue<bool> mEnableShadows{ mIndex, "Shadows", "enable shadows" };
SettingValue<float> mShadowFadeStart{ "Shadows", "shadow fade start", makeClampSanitizerFloat(0, 1) }; SettingValue<int> mNumberOfShadowMaps{ mIndex, "Shadows", "number of shadow maps",
SettingValue<bool> mAllowShadowMapOverlap{ "Shadows", "allow shadow map overlap" }; makeClampSanitizerInt(1, 8) };
SettingValue<float> mSplitPointUniformLogarithmicRatio{ "Shadows", "split point uniform logarithmic ratio", SettingValue<float> mMaximumShadowMapDistance{ mIndex, "Shadows", "maximum shadow map distance" };
makeClampSanitizerFloat(0, 1) }; SettingValue<float> mShadowFadeStart{ mIndex, "Shadows", "shadow fade start", makeClampSanitizerFloat(0, 1) };
SettingValue<float> mSplitPointBias{ "Shadows", "split point bias" }; SettingValue<bool> mAllowShadowMapOverlap{ mIndex, "Shadows", "allow shadow map overlap" };
SettingValue<bool> mEnableDebugHud{ "Shadows", "enable debug hud" }; SettingValue<float> mSplitPointUniformLogarithmicRatio{ mIndex, "Shadows",
SettingValue<bool> mEnableDebugOverlay{ "Shadows", "enable debug overlay" }; "split point uniform logarithmic ratio", makeClampSanitizerFloat(0, 1) };
SettingValue<std::string> mComputeSceneBounds{ "Shadows", "compute scene bounds", SettingValue<float> mSplitPointBias{ mIndex, "Shadows", "split point bias" };
SettingValue<bool> mEnableDebugHud{ mIndex, "Shadows", "enable debug hud" };
SettingValue<bool> mEnableDebugOverlay{ mIndex, "Shadows", "enable debug overlay" };
SettingValue<std::string> mComputeSceneBounds{ mIndex, "Shadows", "compute scene bounds",
makeEnumSanitizerString({ "primitives", "bounds", "none" }) }; makeEnumSanitizerString({ "primitives", "bounds", "none" }) };
SettingValue<int> mShadowMapResolution{ "Shadows", "shadow map resolution" }; SettingValue<int> mShadowMapResolution{ mIndex, "Shadows", "shadow map resolution" };
SettingValue<float> mMinimumLispsmNearFarRatio{ "Shadows", "minimum lispsm near far ratio", SettingValue<float> mMinimumLispsmNearFarRatio{ mIndex, "Shadows", "minimum lispsm near far ratio",
makeMaxStrictSanitizerFloat(0) }; makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mPolygonOffsetFactor{ "Shadows", "polygon offset factor" }; SettingValue<float> mPolygonOffsetFactor{ mIndex, "Shadows", "polygon offset factor" };
SettingValue<float> mPolygonOffsetUnits{ "Shadows", "polygon offset units" }; SettingValue<float> mPolygonOffsetUnits{ mIndex, "Shadows", "polygon offset units" };
SettingValue<float> mNormalOffsetDistance{ "Shadows", "normal offset distance" }; SettingValue<float> mNormalOffsetDistance{ mIndex, "Shadows", "normal offset distance" };
SettingValue<bool> mUseFrontFaceCulling{ "Shadows", "use front face culling" }; SettingValue<bool> mUseFrontFaceCulling{ mIndex, "Shadows", "use front face culling" };
SettingValue<bool> mActorShadows{ "Shadows", "actor shadows" }; SettingValue<bool> mActorShadows{ mIndex, "Shadows", "actor shadows" };
SettingValue<bool> mPlayerShadows{ "Shadows", "player shadows" }; SettingValue<bool> mPlayerShadows{ mIndex, "Shadows", "player shadows" };
SettingValue<bool> mTerrainShadows{ "Shadows", "terrain shadows" }; SettingValue<bool> mTerrainShadows{ mIndex, "Shadows", "terrain shadows" };
SettingValue<bool> mObjectShadows{ "Shadows", "object shadows" }; SettingValue<bool> mObjectShadows{ mIndex, "Shadows", "object shadows" };
SettingValue<bool> mEnableIndoorShadows{ "Shadows", "enable indoor shadows" }; SettingValue<bool> mEnableIndoorShadows{ mIndex, "Shadows", "enable indoor shadows" };
}; };
} }

@ -14,18 +14,20 @@
namespace Settings namespace Settings
{ {
struct SoundCategory struct SoundCategory : WithIndex
{ {
SettingValue<std::string> mDevice{ "Sound", "device" }; using WithIndex::WithIndex;
SettingValue<float> mMasterVolume{ "Sound", "master volume", makeClampSanitizerFloat(0, 1) };
SettingValue<float> mFootstepsVolume{ "Sound", "footsteps volume", makeClampSanitizerFloat(0, 1) }; SettingValue<std::string> mDevice{ mIndex, "Sound", "device" };
SettingValue<float> mMusicVolume{ "Sound", "music volume", makeClampSanitizerFloat(0, 1) }; SettingValue<float> mMasterVolume{ mIndex, "Sound", "master volume", makeClampSanitizerFloat(0, 1) };
SettingValue<float> mSfxVolume{ "Sound", "sfx volume", makeClampSanitizerFloat(0, 1) }; SettingValue<float> mFootstepsVolume{ mIndex, "Sound", "footsteps volume", makeClampSanitizerFloat(0, 1) };
SettingValue<float> mVoiceVolume{ "Sound", "voice volume", makeClampSanitizerFloat(0, 1) }; SettingValue<float> mMusicVolume{ mIndex, "Sound", "music volume", makeClampSanitizerFloat(0, 1) };
SettingValue<int> mBufferCacheMin{ "Sound", "buffer cache min", makeMaxSanitizerInt(1) }; SettingValue<float> mSfxVolume{ mIndex, "Sound", "sfx volume", makeClampSanitizerFloat(0, 1) };
SettingValue<int> mBufferCacheMax{ "Sound", "buffer cache max", makeMaxSanitizerInt(1) }; SettingValue<float> mVoiceVolume{ mIndex, "Sound", "voice volume", makeClampSanitizerFloat(0, 1) };
SettingValue<int> mHrtfEnable{ "Sound", "hrtf enable", makeEnumSanitizerInt({ -1, 0, 1 }) }; SettingValue<int> mBufferCacheMin{ mIndex, "Sound", "buffer cache min", makeMaxSanitizerInt(1) };
SettingValue<std::string> mHrtf{ "Sound", "hrtf" }; SettingValue<int> mBufferCacheMax{ mIndex, "Sound", "buffer cache max", makeMaxSanitizerInt(1) };
SettingValue<int> mHrtfEnable{ mIndex, "Sound", "hrtf enable", makeEnumSanitizerInt({ -1, 0, 1 }) };
SettingValue<std::string> mHrtf{ mIndex, "Sound", "hrtf" };
}; };
} }

@ -14,14 +14,16 @@
namespace Settings namespace Settings
{ {
struct StereoCategory struct StereoCategory : WithIndex
{ {
SettingValue<bool> mStereoEnabled{ "Stereo", "stereo enabled" }; using WithIndex::WithIndex;
SettingValue<bool> mMultiview{ "Stereo", "multiview" };
SettingValue<bool> mSharedShadowMaps{ "Stereo", "shared shadow maps" }; SettingValue<bool> mStereoEnabled{ mIndex, "Stereo", "stereo enabled" };
SettingValue<bool> mAllowDisplayListsForMultiview{ "Stereo", "allow display lists for multiview" }; SettingValue<bool> mMultiview{ mIndex, "Stereo", "multiview" };
SettingValue<bool> mUseCustomView{ "Stereo", "use custom view" }; SettingValue<bool> mSharedShadowMaps{ mIndex, "Stereo", "shared shadow maps" };
SettingValue<bool> mUseCustomEyeResolution{ "Stereo", "use custom eye resolution" }; SettingValue<bool> mAllowDisplayListsForMultiview{ mIndex, "Stereo", "allow display lists for multiview" };
SettingValue<bool> mUseCustomView{ mIndex, "Stereo", "use custom view" };
SettingValue<bool> mUseCustomEyeResolution{ mIndex, "Stereo", "use custom eye resolution" };
}; };
} }

@ -14,47 +14,49 @@
namespace Settings namespace Settings
{ {
struct StereoViewCategory struct StereoViewCategory : WithIndex
{ {
SettingValue<int> mEyeResolutionX{ "Stereo View", "eye resolution x", makeMaxSanitizerInt(1) }; using WithIndex::WithIndex;
SettingValue<int> mEyeResolutionY{ "Stereo View", "eye resolution y", makeMaxSanitizerInt(1) };
SettingValue<double> mLeftEyeOffsetX{ "Stereo View", "left eye offset x" }; SettingValue<int> mEyeResolutionX{ mIndex, "Stereo View", "eye resolution x", makeMaxSanitizerInt(1) };
SettingValue<double> mLeftEyeOffsetY{ "Stereo View", "left eye offset y" }; SettingValue<int> mEyeResolutionY{ mIndex, "Stereo View", "eye resolution y", makeMaxSanitizerInt(1) };
SettingValue<double> mLeftEyeOffsetZ{ "Stereo View", "left eye offset z" }; SettingValue<double> mLeftEyeOffsetX{ mIndex, "Stereo View", "left eye offset x" };
SettingValue<double> mLeftEyeOrientationX{ "Stereo View", "left eye orientation x", SettingValue<double> mLeftEyeOffsetY{ mIndex, "Stereo View", "left eye offset y" };
SettingValue<double> mLeftEyeOffsetZ{ mIndex, "Stereo View", "left eye offset z" };
SettingValue<double> mLeftEyeOrientationX{ mIndex, "Stereo View", "left eye orientation x",
makeClampSanitizerDouble(-1, 1) }; makeClampSanitizerDouble(-1, 1) };
SettingValue<double> mLeftEyeOrientationY{ "Stereo View", "left eye orientation y", SettingValue<double> mLeftEyeOrientationY{ mIndex, "Stereo View", "left eye orientation y",
makeClampSanitizerDouble(-1, 1) }; makeClampSanitizerDouble(-1, 1) };
SettingValue<double> mLeftEyeOrientationZ{ "Stereo View", "left eye orientation z", SettingValue<double> mLeftEyeOrientationZ{ mIndex, "Stereo View", "left eye orientation z",
makeClampSanitizerDouble(-1, 1) }; makeClampSanitizerDouble(-1, 1) };
SettingValue<double> mLeftEyeOrientationW{ "Stereo View", "left eye orientation w", SettingValue<double> mLeftEyeOrientationW{ mIndex, "Stereo View", "left eye orientation w",
makeClampSanitizerDouble(-1, 1) }; makeClampSanitizerDouble(-1, 1) };
SettingValue<double> mLeftEyeFovLeft{ "Stereo View", "left eye fov left", SettingValue<double> mLeftEyeFovLeft{ mIndex, "Stereo View", "left eye fov left",
makeClampSanitizerDouble(-osg::PI, osg::PI) }; makeClampSanitizerDouble(-osg::PI, osg::PI) };
SettingValue<double> mLeftEyeFovRight{ "Stereo View", "left eye fov right", SettingValue<double> mLeftEyeFovRight{ mIndex, "Stereo View", "left eye fov right",
makeClampSanitizerDouble(-osg::PI, osg::PI) }; makeClampSanitizerDouble(-osg::PI, osg::PI) };
SettingValue<double> mLeftEyeFovUp{ "Stereo View", "left eye fov up", SettingValue<double> mLeftEyeFovUp{ mIndex, "Stereo View", "left eye fov up",
makeClampSanitizerDouble(-osg::PI, osg::PI) }; makeClampSanitizerDouble(-osg::PI, osg::PI) };
SettingValue<double> mLeftEyeFovDown{ "Stereo View", "left eye fov down", SettingValue<double> mLeftEyeFovDown{ mIndex, "Stereo View", "left eye fov down",
makeClampSanitizerDouble(-osg::PI, osg::PI) }; makeClampSanitizerDouble(-osg::PI, osg::PI) };
SettingValue<double> mRightEyeOffsetX{ "Stereo View", "right eye offset x" }; SettingValue<double> mRightEyeOffsetX{ mIndex, "Stereo View", "right eye offset x" };
SettingValue<double> mRightEyeOffsetY{ "Stereo View", "right eye offset y" }; SettingValue<double> mRightEyeOffsetY{ mIndex, "Stereo View", "right eye offset y" };
SettingValue<double> mRightEyeOffsetZ{ "Stereo View", "right eye offset z" }; SettingValue<double> mRightEyeOffsetZ{ mIndex, "Stereo View", "right eye offset z" };
SettingValue<double> mRightEyeOrientationX{ "Stereo View", "right eye orientation x", SettingValue<double> mRightEyeOrientationX{ mIndex, "Stereo View", "right eye orientation x",
makeClampSanitizerDouble(-1, 1) }; makeClampSanitizerDouble(-1, 1) };
SettingValue<double> mRightEyeOrientationY{ "Stereo View", "right eye orientation y", SettingValue<double> mRightEyeOrientationY{ mIndex, "Stereo View", "right eye orientation y",
makeClampSanitizerDouble(-1, 1) }; makeClampSanitizerDouble(-1, 1) };
SettingValue<double> mRightEyeOrientationZ{ "Stereo View", "right eye orientation z", SettingValue<double> mRightEyeOrientationZ{ mIndex, "Stereo View", "right eye orientation z",
makeClampSanitizerDouble(-1, 1) }; makeClampSanitizerDouble(-1, 1) };
SettingValue<double> mRightEyeOrientationW{ "Stereo View", "right eye orientation w", SettingValue<double> mRightEyeOrientationW{ mIndex, "Stereo View", "right eye orientation w",
makeClampSanitizerDouble(-1, 1) }; makeClampSanitizerDouble(-1, 1) };
SettingValue<double> mRightEyeFovLeft{ "Stereo View", "right eye fov left", SettingValue<double> mRightEyeFovLeft{ mIndex, "Stereo View", "right eye fov left",
makeClampSanitizerDouble(-osg::PI, osg::PI) }; makeClampSanitizerDouble(-osg::PI, osg::PI) };
SettingValue<double> mRightEyeFovRight{ "Stereo View", "right eye fov right", SettingValue<double> mRightEyeFovRight{ mIndex, "Stereo View", "right eye fov right",
makeClampSanitizerDouble(-osg::PI, osg::PI) }; makeClampSanitizerDouble(-osg::PI, osg::PI) };
SettingValue<double> mRightEyeFovUp{ "Stereo View", "right eye fov up", SettingValue<double> mRightEyeFovUp{ mIndex, "Stereo View", "right eye fov up",
makeClampSanitizerDouble(-osg::PI, osg::PI) }; makeClampSanitizerDouble(-osg::PI, osg::PI) };
SettingValue<double> mRightEyeFovDown{ "Stereo View", "right eye fov down", SettingValue<double> mRightEyeFovDown{ mIndex, "Stereo View", "right eye fov down",
makeClampSanitizerDouble(-osg::PI, osg::PI) }; makeClampSanitizerDouble(-osg::PI, osg::PI) };
}; };
} }

@ -14,25 +14,29 @@
namespace Settings namespace Settings
{ {
struct TerrainCategory struct TerrainCategory : WithIndex
{ {
SettingValue<bool> mDistantTerrain{ "Terrain", "distant terrain" }; using WithIndex::WithIndex;
SettingValue<float> mLodFactor{ "Terrain", "lod factor", makeMaxStrictSanitizerFloat(0) };
SettingValue<int> mVertexLodMod{ "Terrain", "vertex lod mod" }; SettingValue<bool> mDistantTerrain{ mIndex, "Terrain", "distant terrain" };
SettingValue<int> mCompositeMapLevel{ "Terrain", "composite map level", makeMaxSanitizerInt(-3) }; SettingValue<float> mLodFactor{ mIndex, "Terrain", "lod factor", makeMaxStrictSanitizerFloat(0) };
SettingValue<int> mCompositeMapResolution{ "Terrain", "composite map resolution", makeMaxSanitizerInt(1) }; SettingValue<int> mVertexLodMod{ mIndex, "Terrain", "vertex lod mod" };
SettingValue<float> mMaxCompositeGeometrySize{ "Terrain", "max composite geometry size", SettingValue<int> mCompositeMapLevel{ mIndex, "Terrain", "composite map level", makeMaxSanitizerInt(-3) };
SettingValue<int> mCompositeMapResolution{ mIndex, "Terrain", "composite map resolution",
makeMaxSanitizerInt(1) };
SettingValue<float> mMaxCompositeGeometrySize{ mIndex, "Terrain", "max composite geometry size",
makeMaxSanitizerFloat(1) }; makeMaxSanitizerFloat(1) };
SettingValue<bool> mDebugChunks{ "Terrain", "debug chunks" }; SettingValue<bool> mDebugChunks{ mIndex, "Terrain", "debug chunks" };
SettingValue<bool> mObjectPaging{ "Terrain", "object paging" }; SettingValue<bool> mObjectPaging{ mIndex, "Terrain", "object paging" };
SettingValue<bool> mObjectPagingActiveGrid{ "Terrain", "object paging active grid" }; SettingValue<bool> mObjectPagingActiveGrid{ mIndex, "Terrain", "object paging active grid" };
SettingValue<float> mObjectPagingMergeFactor{ "Terrain", "object paging merge factor", SettingValue<float> mObjectPagingMergeFactor{ mIndex, "Terrain", "object paging merge factor",
makeMaxStrictSanitizerFloat(0) }; makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mObjectPagingMinSize{ "Terrain", "object paging min size", makeMaxStrictSanitizerFloat(0) }; SettingValue<float> mObjectPagingMinSize{ mIndex, "Terrain", "object paging min size",
SettingValue<float> mObjectPagingMinSizeMergeFactor{ "Terrain", "object paging min size merge factor",
makeMaxStrictSanitizerFloat(0) }; makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mObjectPagingMinSizeCostMultiplier{ "Terrain", "object paging min size cost multiplier", SettingValue<float> mObjectPagingMinSizeMergeFactor{ mIndex, "Terrain", "object paging min size merge factor",
makeMaxStrictSanitizerFloat(0) }; makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mObjectPagingMinSizeCostMultiplier{ mIndex, "Terrain",
"object paging min size cost multiplier", makeMaxStrictSanitizerFloat(0) };
}; };
} }

@ -14,20 +14,22 @@
namespace Settings namespace Settings
{ {
struct VideoCategory struct VideoCategory : WithIndex
{ {
SettingValue<int> mResolutionX{ "Video", "resolution x", makeMaxSanitizerInt(1) }; using WithIndex::WithIndex;
SettingValue<int> mResolutionY{ "Video", "resolution y", makeMaxSanitizerInt(1) };
SettingValue<int> mWindowMode{ "Video", "window mode", makeEnumSanitizerInt({ 0, 1, 2 }) }; SettingValue<int> mResolutionX{ mIndex, "Video", "resolution x", makeMaxSanitizerInt(1) };
SettingValue<int> mScreen{ "Video", "screen", makeMaxSanitizerInt(0) }; SettingValue<int> mResolutionY{ mIndex, "Video", "resolution y", makeMaxSanitizerInt(1) };
SettingValue<bool> mMinimizeOnFocusLoss{ "Video", "minimize on focus loss" }; SettingValue<int> mWindowMode{ mIndex, "Video", "window mode", makeEnumSanitizerInt({ 0, 1, 2 }) };
SettingValue<bool> mWindowBorder{ "Video", "window border" }; SettingValue<int> mScreen{ mIndex, "Video", "screen", makeMaxSanitizerInt(0) };
SettingValue<int> mAntialiasing{ "Video", "antialiasing", makeEnumSanitizerInt({ 0, 2, 4, 8, 16 }) }; SettingValue<bool> mMinimizeOnFocusLoss{ mIndex, "Video", "minimize on focus loss" };
SettingValue<int> mVsyncMode{ "Video", "vsync mode", makeEnumSanitizerInt({ 0, 1, 2 }) }; SettingValue<bool> mWindowBorder{ mIndex, "Video", "window border" };
SettingValue<float> mFramerateLimit{ "Video", "framerate limit", makeMaxSanitizerFloat(0) }; SettingValue<int> mAntialiasing{ mIndex, "Video", "antialiasing", makeEnumSanitizerInt({ 0, 2, 4, 8, 16 }) };
SettingValue<float> mContrast{ "Video", "contrast", makeMaxStrictSanitizerFloat(0) }; SettingValue<int> mVsyncMode{ mIndex, "Video", "vsync mode", makeEnumSanitizerInt({ 0, 1, 2 }) };
SettingValue<float> mGamma{ "Video", "gamma", makeMaxStrictSanitizerFloat(0) }; SettingValue<float> mFramerateLimit{ mIndex, "Video", "framerate limit", makeMaxSanitizerFloat(0) };
SettingValue<std::string> mScreenshotType{ "Video", "screenshot type" }; SettingValue<float> mContrast{ mIndex, "Video", "contrast", makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mGamma{ mIndex, "Video", "gamma", makeMaxStrictSanitizerFloat(0) };
SettingValue<std::string> mScreenshotType{ mIndex, "Video", "screenshot type" };
}; };
} }

@ -14,16 +14,19 @@
namespace Settings namespace Settings
{ {
struct WaterCategory struct WaterCategory : WithIndex
{ {
SettingValue<bool> mShader{ "Water", "shader" }; using WithIndex::WithIndex;
SettingValue<int> mRttSize{ "Water", "rtt size", makeMaxSanitizerInt(1) };
SettingValue<bool> mRefraction{ "Water", "refraction" }; SettingValue<bool> mShader{ mIndex, "Water", "shader" };
SettingValue<int> mReflectionDetail{ "Water", "reflection detail", makeEnumSanitizerInt({ 0, 1, 2, 3, 4, 5 }) }; SettingValue<int> mRttSize{ mIndex, "Water", "rtt size", makeMaxSanitizerInt(1) };
SettingValue<int> mRainRippleDetail{ "Water", "rain ripple detail", makeEnumSanitizerInt({ 0, 1, 2 }) }; SettingValue<bool> mRefraction{ mIndex, "Water", "refraction" };
SettingValue<float> mSmallFeatureCullingPixelSize{ "Water", "small feature culling pixel size", SettingValue<int> mReflectionDetail{ mIndex, "Water", "reflection detail",
makeEnumSanitizerInt({ 0, 1, 2, 3, 4, 5 }) };
SettingValue<int> mRainRippleDetail{ mIndex, "Water", "rain ripple detail", makeEnumSanitizerInt({ 0, 1, 2 }) };
SettingValue<float> mSmallFeatureCullingPixelSize{ mIndex, "Water", "small feature culling pixel size",
makeMaxStrictSanitizerFloat(0) }; makeMaxStrictSanitizerFloat(0) };
SettingValue<float> mRefractionScale{ "Water", "refraction scale", makeClampSanitizerFloat(0, 1) }; SettingValue<float> mRefractionScale{ mIndex, "Water", "refraction scale", makeClampSanitizerFloat(0, 1) };
}; };
} }

@ -14,151 +14,153 @@
namespace Settings namespace Settings
{ {
struct WindowsCategory struct WindowsCategory : WithIndex
{ {
SettingValue<float> mStatsX{ "Windows", "stats x" }; using WithIndex::WithIndex;
SettingValue<float> mStatsY{ "Windows", "stats y" };
SettingValue<float> mStatsW{ "Windows", "stats w" }; SettingValue<float> mStatsX{ mIndex, "Windows", "stats x" };
SettingValue<float> mStatsH{ "Windows", "stats h" }; SettingValue<float> mStatsY{ mIndex, "Windows", "stats y" };
SettingValue<float> mStatsMaximizedX{ "Windows", "stats maximized x" }; SettingValue<float> mStatsW{ mIndex, "Windows", "stats w" };
SettingValue<float> mStatsMaximizedY{ "Windows", "stats maximized y" }; SettingValue<float> mStatsH{ mIndex, "Windows", "stats h" };
SettingValue<float> mStatsMaximizedW{ "Windows", "stats maximized w" }; SettingValue<float> mStatsMaximizedX{ mIndex, "Windows", "stats maximized x" };
SettingValue<float> mStatsMaximizedH{ "Windows", "stats maximized h" }; SettingValue<float> mStatsMaximizedY{ mIndex, "Windows", "stats maximized y" };
SettingValue<bool> mStatsPin{ "Windows", "stats pin" }; SettingValue<float> mStatsMaximizedW{ mIndex, "Windows", "stats maximized w" };
SettingValue<bool> mStatsHidden{ "Windows", "stats hidden" }; SettingValue<float> mStatsMaximizedH{ mIndex, "Windows", "stats maximized h" };
SettingValue<bool> mStatsMaximized{ "Windows", "stats maximized" }; SettingValue<bool> mStatsPin{ mIndex, "Windows", "stats pin" };
SettingValue<float> mSpellsX{ "Windows", "spells x" }; SettingValue<bool> mStatsHidden{ mIndex, "Windows", "stats hidden" };
SettingValue<float> mSpellsY{ "Windows", "spells y" }; SettingValue<bool> mStatsMaximized{ mIndex, "Windows", "stats maximized" };
SettingValue<float> mSpellsW{ "Windows", "spells w" }; SettingValue<float> mSpellsX{ mIndex, "Windows", "spells x" };
SettingValue<float> mSpellsH{ "Windows", "spells h" }; SettingValue<float> mSpellsY{ mIndex, "Windows", "spells y" };
SettingValue<float> mSpellsMaximizedX{ "Windows", "spells maximized x" }; SettingValue<float> mSpellsW{ mIndex, "Windows", "spells w" };
SettingValue<float> mSpellsMaximizedY{ "Windows", "spells maximized y" }; SettingValue<float> mSpellsH{ mIndex, "Windows", "spells h" };
SettingValue<float> mSpellsMaximizedW{ "Windows", "spells maximized w" }; SettingValue<float> mSpellsMaximizedX{ mIndex, "Windows", "spells maximized x" };
SettingValue<float> mSpellsMaximizedH{ "Windows", "spells maximized h" }; SettingValue<float> mSpellsMaximizedY{ mIndex, "Windows", "spells maximized y" };
SettingValue<bool> mSpellsPin{ "Windows", "spells pin" }; SettingValue<float> mSpellsMaximizedW{ mIndex, "Windows", "spells maximized w" };
SettingValue<bool> mSpellsHidden{ "Windows", "spells hidden" }; SettingValue<float> mSpellsMaximizedH{ mIndex, "Windows", "spells maximized h" };
SettingValue<bool> mSpellsMaximized{ "Windows", "spells maximized" }; SettingValue<bool> mSpellsPin{ mIndex, "Windows", "spells pin" };
SettingValue<float> mMapX{ "Windows", "map x" }; SettingValue<bool> mSpellsHidden{ mIndex, "Windows", "spells hidden" };
SettingValue<float> mMapY{ "Windows", "map y" }; SettingValue<bool> mSpellsMaximized{ mIndex, "Windows", "spells maximized" };
SettingValue<float> mMapW{ "Windows", "map w" }; SettingValue<float> mMapX{ mIndex, "Windows", "map x" };
SettingValue<float> mMapH{ "Windows", "map h" }; SettingValue<float> mMapY{ mIndex, "Windows", "map y" };
SettingValue<float> mMapMaximizedX{ "Windows", "map maximized x" }; SettingValue<float> mMapW{ mIndex, "Windows", "map w" };
SettingValue<float> mMapMaximizedY{ "Windows", "map maximized y" }; SettingValue<float> mMapH{ mIndex, "Windows", "map h" };
SettingValue<float> mMapMaximizedW{ "Windows", "map maximized w" }; SettingValue<float> mMapMaximizedX{ mIndex, "Windows", "map maximized x" };
SettingValue<float> mMapMaximizedH{ "Windows", "map maximized h" }; SettingValue<float> mMapMaximizedY{ mIndex, "Windows", "map maximized y" };
SettingValue<bool> mMapPin{ "Windows", "map pin" }; SettingValue<float> mMapMaximizedW{ mIndex, "Windows", "map maximized w" };
SettingValue<bool> mMapHidden{ "Windows", "map hidden" }; SettingValue<float> mMapMaximizedH{ mIndex, "Windows", "map maximized h" };
SettingValue<bool> mMapMaximized{ "Windows", "map maximized" }; SettingValue<bool> mMapPin{ mIndex, "Windows", "map pin" };
SettingValue<float> mInventoryX{ "Windows", "inventory x" }; SettingValue<bool> mMapHidden{ mIndex, "Windows", "map hidden" };
SettingValue<float> mInventoryY{ "Windows", "inventory y" }; SettingValue<bool> mMapMaximized{ mIndex, "Windows", "map maximized" };
SettingValue<float> mInventoryW{ "Windows", "inventory w" }; SettingValue<float> mInventoryX{ mIndex, "Windows", "inventory x" };
SettingValue<float> mInventoryH{ "Windows", "inventory h" }; SettingValue<float> mInventoryY{ mIndex, "Windows", "inventory y" };
SettingValue<float> mInventoryMaximizedX{ "Windows", "inventory maximized x" }; SettingValue<float> mInventoryW{ mIndex, "Windows", "inventory w" };
SettingValue<float> mInventoryMaximizedY{ "Windows", "inventory maximized y" }; SettingValue<float> mInventoryH{ mIndex, "Windows", "inventory h" };
SettingValue<float> mInventoryMaximizedW{ "Windows", "inventory maximized w" }; SettingValue<float> mInventoryMaximizedX{ mIndex, "Windows", "inventory maximized x" };
SettingValue<float> mInventoryMaximizedH{ "Windows", "inventory maximized h" }; SettingValue<float> mInventoryMaximizedY{ mIndex, "Windows", "inventory maximized y" };
SettingValue<bool> mInventoryPin{ "Windows", "inventory pin" }; SettingValue<float> mInventoryMaximizedW{ mIndex, "Windows", "inventory maximized w" };
SettingValue<bool> mInventoryHidden{ "Windows", "inventory hidden" }; SettingValue<float> mInventoryMaximizedH{ mIndex, "Windows", "inventory maximized h" };
SettingValue<bool> mInventoryMaximized{ "Windows", "inventory maximized" }; SettingValue<bool> mInventoryPin{ mIndex, "Windows", "inventory pin" };
SettingValue<float> mInventoryContainerX{ "Windows", "inventory container x" }; SettingValue<bool> mInventoryHidden{ mIndex, "Windows", "inventory hidden" };
SettingValue<float> mInventoryContainerY{ "Windows", "inventory container y" }; SettingValue<bool> mInventoryMaximized{ mIndex, "Windows", "inventory maximized" };
SettingValue<float> mInventoryContainerW{ "Windows", "inventory container w" }; SettingValue<float> mInventoryContainerX{ mIndex, "Windows", "inventory container x" };
SettingValue<float> mInventoryContainerH{ "Windows", "inventory container h" }; SettingValue<float> mInventoryContainerY{ mIndex, "Windows", "inventory container y" };
SettingValue<float> mInventoryContainerMaximizedX{ "Windows", "inventory container maximized x" }; SettingValue<float> mInventoryContainerW{ mIndex, "Windows", "inventory container w" };
SettingValue<float> mInventoryContainerMaximizedY{ "Windows", "inventory container maximized y" }; SettingValue<float> mInventoryContainerH{ mIndex, "Windows", "inventory container h" };
SettingValue<float> mInventoryContainerMaximizedW{ "Windows", "inventory container maximized w" }; SettingValue<float> mInventoryContainerMaximizedX{ mIndex, "Windows", "inventory container maximized x" };
SettingValue<float> mInventoryContainerMaximizedH{ "Windows", "inventory container maximized h" }; SettingValue<float> mInventoryContainerMaximizedY{ mIndex, "Windows", "inventory container maximized y" };
SettingValue<bool> mInventoryContainerMaximized{ "Windows", "inventory container maximized" }; SettingValue<float> mInventoryContainerMaximizedW{ mIndex, "Windows", "inventory container maximized w" };
SettingValue<float> mInventoryBarterX{ "Windows", "inventory barter x" }; SettingValue<float> mInventoryContainerMaximizedH{ mIndex, "Windows", "inventory container maximized h" };
SettingValue<float> mInventoryBarterY{ "Windows", "inventory barter y" }; SettingValue<bool> mInventoryContainerMaximized{ mIndex, "Windows", "inventory container maximized" };
SettingValue<float> mInventoryBarterW{ "Windows", "inventory barter w" }; SettingValue<float> mInventoryBarterX{ mIndex, "Windows", "inventory barter x" };
SettingValue<float> mInventoryBarterH{ "Windows", "inventory barter h" }; SettingValue<float> mInventoryBarterY{ mIndex, "Windows", "inventory barter y" };
SettingValue<float> mInventoryBarterMaximizedX{ "Windows", "inventory barter maximized x" }; SettingValue<float> mInventoryBarterW{ mIndex, "Windows", "inventory barter w" };
SettingValue<float> mInventoryBarterMaximizedY{ "Windows", "inventory barter maximized y" }; SettingValue<float> mInventoryBarterH{ mIndex, "Windows", "inventory barter h" };
SettingValue<float> mInventoryBarterMaximizedW{ "Windows", "inventory barter maximized w" }; SettingValue<float> mInventoryBarterMaximizedX{ mIndex, "Windows", "inventory barter maximized x" };
SettingValue<float> mInventoryBarterMaximizedH{ "Windows", "inventory barter maximized h" }; SettingValue<float> mInventoryBarterMaximizedY{ mIndex, "Windows", "inventory barter maximized y" };
SettingValue<bool> mInventoryBarterMaximized{ "Windows", "inventory barter maximized" }; SettingValue<float> mInventoryBarterMaximizedW{ mIndex, "Windows", "inventory barter maximized w" };
SettingValue<float> mInventoryCompanionX{ "Windows", "inventory companion x" }; SettingValue<float> mInventoryBarterMaximizedH{ mIndex, "Windows", "inventory barter maximized h" };
SettingValue<float> mInventoryCompanionY{ "Windows", "inventory companion y" }; SettingValue<bool> mInventoryBarterMaximized{ mIndex, "Windows", "inventory barter maximized" };
SettingValue<float> mInventoryCompanionW{ "Windows", "inventory companion w" }; SettingValue<float> mInventoryCompanionX{ mIndex, "Windows", "inventory companion x" };
SettingValue<float> mInventoryCompanionH{ "Windows", "inventory companion h" }; SettingValue<float> mInventoryCompanionY{ mIndex, "Windows", "inventory companion y" };
SettingValue<float> mInventoryCompanionMaximizedX{ "Windows", "inventory companion maximized x" }; SettingValue<float> mInventoryCompanionW{ mIndex, "Windows", "inventory companion w" };
SettingValue<float> mInventoryCompanionMaximizedY{ "Windows", "inventory companion maximized y" }; SettingValue<float> mInventoryCompanionH{ mIndex, "Windows", "inventory companion h" };
SettingValue<float> mInventoryCompanionMaximizedW{ "Windows", "inventory companion maximized w" }; SettingValue<float> mInventoryCompanionMaximizedX{ mIndex, "Windows", "inventory companion maximized x" };
SettingValue<float> mInventoryCompanionMaximizedH{ "Windows", "inventory companion maximized h" }; SettingValue<float> mInventoryCompanionMaximizedY{ mIndex, "Windows", "inventory companion maximized y" };
SettingValue<bool> mInventoryCompanionMaximized{ "Windows", "inventory companion maximized" }; SettingValue<float> mInventoryCompanionMaximizedW{ mIndex, "Windows", "inventory companion maximized w" };
SettingValue<float> mDialogueX{ "Windows", "dialogue x" }; SettingValue<float> mInventoryCompanionMaximizedH{ mIndex, "Windows", "inventory companion maximized h" };
SettingValue<float> mDialogueY{ "Windows", "dialogue y" }; SettingValue<bool> mInventoryCompanionMaximized{ mIndex, "Windows", "inventory companion maximized" };
SettingValue<float> mDialogueW{ "Windows", "dialogue w" }; SettingValue<float> mDialogueX{ mIndex, "Windows", "dialogue x" };
SettingValue<float> mDialogueH{ "Windows", "dialogue h" }; SettingValue<float> mDialogueY{ mIndex, "Windows", "dialogue y" };
SettingValue<float> mDialogueMaximizedX{ "Windows", "dialogue maximized x" }; SettingValue<float> mDialogueW{ mIndex, "Windows", "dialogue w" };
SettingValue<float> mDialogueMaximizedY{ "Windows", "dialogue maximized y" }; SettingValue<float> mDialogueH{ mIndex, "Windows", "dialogue h" };
SettingValue<float> mDialogueMaximizedW{ "Windows", "dialogue maximized w" }; SettingValue<float> mDialogueMaximizedX{ mIndex, "Windows", "dialogue maximized x" };
SettingValue<float> mDialogueMaximizedH{ "Windows", "dialogue maximized h" }; SettingValue<float> mDialogueMaximizedY{ mIndex, "Windows", "dialogue maximized y" };
SettingValue<bool> mDialogueMaximized{ "Windows", "dialogue maximized" }; SettingValue<float> mDialogueMaximizedW{ mIndex, "Windows", "dialogue maximized w" };
SettingValue<float> mAlchemyX{ "Windows", "alchemy x" }; SettingValue<float> mDialogueMaximizedH{ mIndex, "Windows", "dialogue maximized h" };
SettingValue<float> mAlchemyY{ "Windows", "alchemy y" }; SettingValue<bool> mDialogueMaximized{ mIndex, "Windows", "dialogue maximized" };
SettingValue<float> mAlchemyW{ "Windows", "alchemy w" }; SettingValue<float> mAlchemyX{ mIndex, "Windows", "alchemy x" };
SettingValue<float> mAlchemyH{ "Windows", "alchemy h" }; SettingValue<float> mAlchemyY{ mIndex, "Windows", "alchemy y" };
SettingValue<float> mAlchemyMaximizedX{ "Windows", "alchemy maximized x" }; SettingValue<float> mAlchemyW{ mIndex, "Windows", "alchemy w" };
SettingValue<float> mAlchemyMaximizedY{ "Windows", "alchemy maximized y" }; SettingValue<float> mAlchemyH{ mIndex, "Windows", "alchemy h" };
SettingValue<float> mAlchemyMaximizedW{ "Windows", "alchemy maximized w" }; SettingValue<float> mAlchemyMaximizedX{ mIndex, "Windows", "alchemy maximized x" };
SettingValue<float> mAlchemyMaximizedH{ "Windows", "alchemy maximized h" }; SettingValue<float> mAlchemyMaximizedY{ mIndex, "Windows", "alchemy maximized y" };
SettingValue<bool> mAlchemyMaximized{ "Windows", "alchemy maximized" }; SettingValue<float> mAlchemyMaximizedW{ mIndex, "Windows", "alchemy maximized w" };
SettingValue<float> mConsoleX{ "Windows", "console x" }; SettingValue<float> mAlchemyMaximizedH{ mIndex, "Windows", "alchemy maximized h" };
SettingValue<float> mConsoleY{ "Windows", "console y" }; SettingValue<bool> mAlchemyMaximized{ mIndex, "Windows", "alchemy maximized" };
SettingValue<float> mConsoleW{ "Windows", "console w" }; SettingValue<float> mConsoleX{ mIndex, "Windows", "console x" };
SettingValue<float> mConsoleH{ "Windows", "console h" }; SettingValue<float> mConsoleY{ mIndex, "Windows", "console y" };
SettingValue<float> mConsoleMaximizedX{ "Windows", "console maximized x" }; SettingValue<float> mConsoleW{ mIndex, "Windows", "console w" };
SettingValue<float> mConsoleMaximizedY{ "Windows", "console maximized y" }; SettingValue<float> mConsoleH{ mIndex, "Windows", "console h" };
SettingValue<float> mConsoleMaximizedW{ "Windows", "console maximized w" }; SettingValue<float> mConsoleMaximizedX{ mIndex, "Windows", "console maximized x" };
SettingValue<float> mConsoleMaximizedH{ "Windows", "console maximized h" }; SettingValue<float> mConsoleMaximizedY{ mIndex, "Windows", "console maximized y" };
SettingValue<bool> mConsoleMaximized{ "Windows", "console maximized" }; SettingValue<float> mConsoleMaximizedW{ mIndex, "Windows", "console maximized w" };
SettingValue<float> mContainerX{ "Windows", "container x" }; SettingValue<float> mConsoleMaximizedH{ mIndex, "Windows", "console maximized h" };
SettingValue<float> mContainerY{ "Windows", "container y" }; SettingValue<bool> mConsoleMaximized{ mIndex, "Windows", "console maximized" };
SettingValue<float> mContainerW{ "Windows", "container w" }; SettingValue<float> mContainerX{ mIndex, "Windows", "container x" };
SettingValue<float> mContainerH{ "Windows", "container h" }; SettingValue<float> mContainerY{ mIndex, "Windows", "container y" };
SettingValue<float> mContainerMaximizedX{ "Windows", "container maximized x" }; SettingValue<float> mContainerW{ mIndex, "Windows", "container w" };
SettingValue<float> mContainerMaximizedY{ "Windows", "container maximized y" }; SettingValue<float> mContainerH{ mIndex, "Windows", "container h" };
SettingValue<float> mContainerMaximizedW{ "Windows", "container maximized w" }; SettingValue<float> mContainerMaximizedX{ mIndex, "Windows", "container maximized x" };
SettingValue<float> mContainerMaximizedH{ "Windows", "container maximized h" }; SettingValue<float> mContainerMaximizedY{ mIndex, "Windows", "container maximized y" };
SettingValue<bool> mContainerMaximized{ "Windows", "container maximized" }; SettingValue<float> mContainerMaximizedW{ mIndex, "Windows", "container maximized w" };
SettingValue<float> mBarterX{ "Windows", "barter x" }; SettingValue<float> mContainerMaximizedH{ mIndex, "Windows", "container maximized h" };
SettingValue<float> mBarterY{ "Windows", "barter y" }; SettingValue<bool> mContainerMaximized{ mIndex, "Windows", "container maximized" };
SettingValue<float> mBarterW{ "Windows", "barter w" }; SettingValue<float> mBarterX{ mIndex, "Windows", "barter x" };
SettingValue<float> mBarterH{ "Windows", "barter h" }; SettingValue<float> mBarterY{ mIndex, "Windows", "barter y" };
SettingValue<float> mBarterMaximizedX{ "Windows", "barter maximized x" }; SettingValue<float> mBarterW{ mIndex, "Windows", "barter w" };
SettingValue<float> mBarterMaximizedY{ "Windows", "barter maximized y" }; SettingValue<float> mBarterH{ mIndex, "Windows", "barter h" };
SettingValue<float> mBarterMaximizedW{ "Windows", "barter maximized w" }; SettingValue<float> mBarterMaximizedX{ mIndex, "Windows", "barter maximized x" };
SettingValue<float> mBarterMaximizedH{ "Windows", "barter maximized h" }; SettingValue<float> mBarterMaximizedY{ mIndex, "Windows", "barter maximized y" };
SettingValue<bool> mBarterMaximized{ "Windows", "barter maximized" }; SettingValue<float> mBarterMaximizedW{ mIndex, "Windows", "barter maximized w" };
SettingValue<float> mCompanionX{ "Windows", "companion x" }; SettingValue<float> mBarterMaximizedH{ mIndex, "Windows", "barter maximized h" };
SettingValue<float> mCompanionY{ "Windows", "companion y" }; SettingValue<bool> mBarterMaximized{ mIndex, "Windows", "barter maximized" };
SettingValue<float> mCompanionW{ "Windows", "companion w" }; SettingValue<float> mCompanionX{ mIndex, "Windows", "companion x" };
SettingValue<float> mCompanionH{ "Windows", "companion h" }; SettingValue<float> mCompanionY{ mIndex, "Windows", "companion y" };
SettingValue<float> mCompanionMaximizedX{ "Windows", "companion maximized x" }; SettingValue<float> mCompanionW{ mIndex, "Windows", "companion w" };
SettingValue<float> mCompanionMaximizedY{ "Windows", "companion maximized y" }; SettingValue<float> mCompanionH{ mIndex, "Windows", "companion h" };
SettingValue<float> mCompanionMaximizedW{ "Windows", "companion maximized w" }; SettingValue<float> mCompanionMaximizedX{ mIndex, "Windows", "companion maximized x" };
SettingValue<float> mCompanionMaximizedH{ "Windows", "companion maximized h" }; SettingValue<float> mCompanionMaximizedY{ mIndex, "Windows", "companion maximized y" };
SettingValue<bool> mCompanionMaximized{ "Windows", "companion maximized" }; SettingValue<float> mCompanionMaximizedW{ mIndex, "Windows", "companion maximized w" };
SettingValue<float> mSettingsX{ "Windows", "settings x" }; SettingValue<float> mCompanionMaximizedH{ mIndex, "Windows", "companion maximized h" };
SettingValue<float> mSettingsY{ "Windows", "settings y" }; SettingValue<bool> mCompanionMaximized{ mIndex, "Windows", "companion maximized" };
SettingValue<float> mSettingsW{ "Windows", "settings w" }; SettingValue<float> mSettingsX{ mIndex, "Windows", "settings x" };
SettingValue<float> mSettingsH{ "Windows", "settings h" }; SettingValue<float> mSettingsY{ mIndex, "Windows", "settings y" };
SettingValue<float> mSettingsMaximizedX{ "Windows", "settings maximized x" }; SettingValue<float> mSettingsW{ mIndex, "Windows", "settings w" };
SettingValue<float> mSettingsMaximizedY{ "Windows", "settings maximized y" }; SettingValue<float> mSettingsH{ mIndex, "Windows", "settings h" };
SettingValue<float> mSettingsMaximizedW{ "Windows", "settings maximized w" }; SettingValue<float> mSettingsMaximizedX{ mIndex, "Windows", "settings maximized x" };
SettingValue<float> mSettingsMaximizedH{ "Windows", "settings maximized h" }; SettingValue<float> mSettingsMaximizedY{ mIndex, "Windows", "settings maximized y" };
SettingValue<bool> mSettingsMaximized{ "Windows", "settings maximized" }; SettingValue<float> mSettingsMaximizedW{ mIndex, "Windows", "settings maximized w" };
SettingValue<float> mPostprocessorH{ "Windows", "postprocessor h" }; SettingValue<float> mSettingsMaximizedH{ mIndex, "Windows", "settings maximized h" };
SettingValue<float> mPostprocessorW{ "Windows", "postprocessor w" }; SettingValue<bool> mSettingsMaximized{ mIndex, "Windows", "settings maximized" };
SettingValue<float> mPostprocessorX{ "Windows", "postprocessor x" }; SettingValue<float> mPostprocessorH{ mIndex, "Windows", "postprocessor h" };
SettingValue<float> mPostprocessorY{ "Windows", "postprocessor y" }; SettingValue<float> mPostprocessorW{ mIndex, "Windows", "postprocessor w" };
SettingValue<float> mPostprocessorMaximizedX{ "Windows", "postprocessor maximized x" }; SettingValue<float> mPostprocessorX{ mIndex, "Windows", "postprocessor x" };
SettingValue<float> mPostprocessorMaximizedY{ "Windows", "postprocessor maximized y" }; SettingValue<float> mPostprocessorY{ mIndex, "Windows", "postprocessor y" };
SettingValue<float> mPostprocessorMaximizedW{ "Windows", "postprocessor maximized w" }; SettingValue<float> mPostprocessorMaximizedX{ mIndex, "Windows", "postprocessor maximized x" };
SettingValue<float> mPostprocessorMaximizedH{ "Windows", "postprocessor maximized h" }; SettingValue<float> mPostprocessorMaximizedY{ mIndex, "Windows", "postprocessor maximized y" };
SettingValue<bool> mPostprocessorMaximized{ "Windows", "postprocessor maximized" }; SettingValue<float> mPostprocessorMaximizedW{ mIndex, "Windows", "postprocessor maximized w" };
SettingValue<float> mPostprocessorMaximizedH{ mIndex, "Windows", "postprocessor maximized h" };
SettingValue<bool> mPostprocessorMaximized{ mIndex, "Windows", "postprocessor maximized" };
}; };
} }

@ -142,7 +142,7 @@ namespace Settings
} }
if (!loadEditorSettings) if (!loadEditorSettings)
Settings::Values::initDefaults(); Settings::StaticValues::initDefaults();
// Load "settings.cfg" or "openmw-cs.cfg" from the last config dir as user settings. This path will be used to // Load "settings.cfg" or "openmw-cs.cfg" from the last config dir as user settings. This path will be used to
// save modified settings. // save modified settings.
@ -151,7 +151,7 @@ namespace Settings
parser.loadSettingsFile(settingspath, mUserSettings, false, false); parser.loadSettingsFile(settingspath, mUserSettings, false, false);
if (!loadEditorSettings) if (!loadEditorSettings)
Settings::Values::init(); Settings::StaticValues::init();
for (const auto& [key, value] : originalDefaultSettings) for (const auto& [key, value] : originalDefaultSettings)
if (!sInitialized.contains(key)) if (!sInitialized.contains(key))

@ -8,28 +8,241 @@
#include <osg/io_utils> #include <osg/io_utils>
#include <map>
#include <memory> #include <memory>
#include <stdexcept> #include <stdexcept>
#include <string>
#include <string_view> #include <string_view>
#include <utility>
namespace Settings namespace Settings
{ {
enum class SettingValueType
{
Bool,
Int,
UnsignedInt,
Long,
UnsignedLong,
LongLong,
UnsignedLongLong,
Float,
Double,
String,
Vec2f,
Vec3f,
};
template <class T> template <class T>
class SettingValue constexpr SettingValueType getSettingValueType();
template <>
inline constexpr SettingValueType getSettingValueType<bool>()
{
return SettingValueType::Bool;
}
template <>
inline constexpr SettingValueType getSettingValueType<int>()
{
return SettingValueType::Int;
}
template <>
inline constexpr SettingValueType getSettingValueType<unsigned int>()
{
return SettingValueType::UnsignedInt;
}
template <>
inline constexpr SettingValueType getSettingValueType<long>()
{
return SettingValueType::Long;
}
template <>
inline constexpr SettingValueType getSettingValueType<unsigned long>()
{
return SettingValueType::UnsignedLong;
}
template <>
inline constexpr SettingValueType getSettingValueType<long long>()
{
return SettingValueType::LongLong;
}
template <>
inline constexpr SettingValueType getSettingValueType<unsigned long long>()
{
return SettingValueType::UnsignedLongLong;
}
template <>
inline constexpr SettingValueType getSettingValueType<float>()
{
return SettingValueType::Float;
}
template <>
inline constexpr SettingValueType getSettingValueType<double>()
{
return SettingValueType::Double;
}
template <>
inline constexpr SettingValueType getSettingValueType<std::string>()
{
return SettingValueType::String;
}
template <>
inline constexpr SettingValueType getSettingValueType<osg::Vec2f>()
{
return SettingValueType::Vec2f;
}
template <>
inline constexpr SettingValueType getSettingValueType<osg::Vec3f>()
{
return SettingValueType::Vec3f;
}
inline constexpr std::string_view getSettingValueTypeName(SettingValueType type)
{
switch (type)
{
case SettingValueType::Bool:
return "bool";
case SettingValueType::Int:
return "int";
case SettingValueType::UnsignedInt:
return "unsigned int";
case SettingValueType::Long:
return "long";
case SettingValueType::UnsignedLong:
return "unsigned long";
case SettingValueType::LongLong:
return "long long";
case SettingValueType::UnsignedLongLong:
return "unsigned long long";
case SettingValueType::Float:
return "float";
case SettingValueType::Double:
return "double";
case SettingValueType::String:
return "string";
case SettingValueType::Vec2f:
return "vec2f";
case SettingValueType::Vec3f:
return "vec3f";
}
return "unsupported";
}
template <class T>
constexpr std::string_view getSettingValueTypeName()
{
return getSettingValueTypeName(getSettingValueType<T>());
}
inline std::string getSettingDescription(SettingValueType type, std::string_view category, std::string_view name)
{
return std::string(getSettingValueTypeName(type)) + " [" + std::string(category) + "] " + std::string(name)
+ " setting";
}
template <class T>
std::string getSettingDescription(std::string_view category, std::string_view name)
{
return getSettingDescription(getSettingValueType<T>(), category, name);
}
class Index;
class BaseSettingValue
{ {
public: public:
explicit SettingValue( const SettingValueType mType;
std::string_view category, std::string_view name, std::unique_ptr<const Sanitizer<T>>&& sanitizer = nullptr) const std::string_view mCategory;
: mCategory(category) const std::string_view mName;
explicit BaseSettingValue(
SettingValueType type, std::string_view category, std::string_view name, Index& index);
BaseSettingValue(const BaseSettingValue& other) = delete;
BaseSettingValue(BaseSettingValue&& other);
BaseSettingValue& operator=(const BaseSettingValue& other) = delete;
BaseSettingValue& operator=(BaseSettingValue&& other) = delete;
private:
Index& mIndex;
};
template <class T>
class SettingValue;
class Index
{
public:
template <class T>
SettingValue<T>* find(std::string_view category, std::string_view name) const;
template <class T>
SettingValue<T>& get(std::string_view category, std::string_view name) const;
void insert(BaseSettingValue* value)
{
if (!mValues.emplace(std::make_pair(value->mCategory, value->mName), value).second)
throw std::invalid_argument("Duplicated setting definition: "
+ getSettingDescription(value->mType, value->mCategory, value->mName));
}
void insertOrAssign(BaseSettingValue* value)
{
mValues.insert_or_assign(std::make_pair(value->mCategory, value->mName), value);
}
private:
std::map<std::pair<std::string_view, std::string_view>, BaseSettingValue*> mValues;
};
inline BaseSettingValue::BaseSettingValue(
SettingValueType type, std::string_view category, std::string_view name, Index& index)
: mType(type)
, mCategory(category)
, mName(name) , mName(name)
, mIndex(index)
{
mIndex.insert(this);
}
inline BaseSettingValue::BaseSettingValue(BaseSettingValue&& other)
: mType(other.mType)
, mCategory(other.mCategory)
, mName(other.mName)
, mIndex(other.mIndex)
{
mIndex.insertOrAssign(this);
}
template <class T>
class SettingValue final : public BaseSettingValue
{
public:
explicit SettingValue(Index& index, std::string_view category, std::string_view name,
std::unique_ptr<const Sanitizer<T>>&& sanitizer = nullptr)
: BaseSettingValue(getSettingValueType<T>(), category, name, index)
, mSanitizer(std::move(sanitizer)) , mSanitizer(std::move(sanitizer))
, mValue(sanitize(Settings::Manager::get<T>(mName, mCategory))) , mValue(sanitize(Settings::Manager::get<T>(mName, mCategory)))
{ {
} }
SettingValue(SettingValue&& other) SettingValue(SettingValue&& other)
: mCategory(other.mCategory) : BaseSettingValue(std::move(other))
, mName(other.mName)
, mSanitizer(std::move(other.mSanitizer)) , mSanitizer(std::move(other.mSanitizer))
, mDefaultValue(std::move(other.mValue)) , mDefaultValue(std::move(other.mValue))
, mValue(sanitize(Settings::Manager::get<T>(mName, mCategory))) , mValue(sanitize(Settings::Manager::get<T>(mName, mCategory)))
@ -57,8 +270,6 @@ namespace Settings
void reset() { set(mDefaultValue); } void reset() { set(mDefaultValue); }
private: private:
const std::string_view mCategory;
const std::string_view mName;
std::unique_ptr<const Sanitizer<T>> mSanitizer; std::unique_ptr<const Sanitizer<T>> mSanitizer;
T mDefaultValue{}; T mDefaultValue{};
T mValue{}; T mValue{};
@ -71,17 +282,51 @@ namespace Settings
{ {
T sanitizedValue = mSanitizer->apply(value); T sanitizedValue = mSanitizer->apply(value);
if (sanitizedValue != value) if (sanitizedValue != value)
Log(Debug::Warning) << "Setting [" << mCategory << "] " << mName Log(Debug::Warning) << getSettingDescription<T>(mCategory, mName)
<< " value is out of allowed values set: " << value << ", sanitized to " << " value is out of allowed values set: " << value << ", sanitized to "
<< sanitizedValue; << sanitizedValue;
return sanitizedValue; return sanitizedValue;
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
throw std::runtime_error("Invalid setting [" + std::string(mCategory) + "] " + std::string(mName) throw std::runtime_error(
+ " value: " + std::string(e.what())); "Invalid " + getSettingDescription<T>(mCategory, mName) + " value: " + std::string(e.what()));
}
}
};
template <class T>
SettingValue<T>* Index::find(std::string_view category, std::string_view name) const
{
const auto it = mValues.find({ category, name });
if (it == mValues.end())
return nullptr;
BaseSettingValue* const value = it->second;
if (value->mType != getSettingValueType<T>())
throw std::invalid_argument(getSettingDescription(value->mType, category, name)
+ " does not match requested type: " + std::string(getSettingValueTypeName<T>()));
return static_cast<SettingValue<T>*>(value);
}
template <class T>
SettingValue<T>& Index::get(std::string_view category, std::string_view name) const
{
SettingValue<T>* const result = find<T>(category, name);
if (result == nullptr)
throw std::invalid_argument(getSettingDescription<T>(category, name) + " is not found");
return *result;
} }
class WithIndex
{
public:
explicit WithIndex(Index& index)
: mIndex(index)
{
} }
protected:
Index& mIndex;
}; };
} }

@ -4,21 +4,24 @@
namespace Settings namespace Settings
{ {
Values* Values::sValues = nullptr; Index* StaticValues::sIndex = nullptr;
Values* StaticValues::sValues = nullptr;
void Values::initDefaults() void StaticValues::initDefaults()
{ {
if (Values::sValues != nullptr) if (sValues != nullptr)
throw std::logic_error("Default settings already initialized"); throw std::logic_error("Default settings already initialized");
static Values values; static Index index;
Values::sValues = &values; static Values values(index);
sIndex = &index;
sValues = &values;
} }
void Values::init() void StaticValues::init()
{ {
if (Values::sValues == nullptr) if (sValues == nullptr)
throw std::logic_error("Default settings are not initialized"); throw std::logic_error("Default settings are not initialized");
static Values values(std::move(*Values::sValues)); static Values values(std::move(*sValues));
Values::sValues = &values; sValues = &values;
} }
} }

@ -26,54 +26,68 @@
#include "categories/video.hpp" #include "categories/video.hpp"
#include "categories/water.hpp" #include "categories/water.hpp"
#include "categories/windows.hpp" #include "categories/windows.hpp"
#include "settingvalue.hpp"
#include <cassert> #include <cassert>
#include <string_view>
namespace Settings namespace Settings
{ {
class Values struct Values : WithIndex
{
using WithIndex::WithIndex;
CameraCategory mCamera{ mIndex };
CellsCategory mCells{ mIndex };
TerrainCategory mTerrain{ mIndex };
FogCategory mFog{ mIndex };
MapCategory mMap{ mIndex };
GUICategory mGUI{ mIndex };
HUDCategory mHUD{ mIndex };
GameCategory mGame{ mIndex };
GeneralCategory mGeneral{ mIndex };
ShadersCategory mShaders{ mIndex };
InputCategory mInput{ mIndex };
SavesCategory mSaves{ mIndex };
SoundCategory mSound{ mIndex };
VideoCategory mVideo{ mIndex };
WaterCategory mWater{ mIndex };
WindowsCategory mWindows{ mIndex };
NavigatorCategory mNavigator{ mIndex };
ShadowsCategory mShadows{ mIndex };
PhysicsCategory mPhysics{ mIndex };
ModelsCategory mModels{ mIndex };
GroundcoverCategory mGroundcover{ mIndex };
LuaCategory mLua{ mIndex };
StereoCategory mStereo{ mIndex };
StereoViewCategory mStereoView{ mIndex };
PostProcessingCategory mPostProcessing{ mIndex };
};
class StaticValues
{ {
public: public:
CameraCategory mCamera;
CellsCategory mCells;
TerrainCategory mTerrain;
FogCategory mFog;
MapCategory mMap;
GUICategory mGUI;
HUDCategory mHUD;
GameCategory mGame;
GeneralCategory mGeneral;
ShadersCategory mShaders;
InputCategory mInput;
SavesCategory mSaves;
SoundCategory mSound;
VideoCategory mVideo;
WaterCategory mWater;
WindowsCategory mWindows;
NavigatorCategory mNavigator;
ShadowsCategory mShadows;
PhysicsCategory mPhysics;
ModelsCategory mModels;
GroundcoverCategory mGroundcover;
LuaCategory mLua;
StereoCategory mStereo;
StereoViewCategory mStereoView;
PostProcessingCategory mPostProcessing;
static void initDefaults(); static void initDefaults();
static void init(); static void init();
private: private:
static Index* sIndex;
static Values* sValues; static Values* sValues;
friend Values& values(); friend Values& values();
template <class T>
friend SettingValue<T>* find(std::string_view category, std::string_view name);
template <class T>
friend SettingValue<T>& get(std::string_view category, std::string_view name);
}; };
inline Values& values() inline Values& values()
{ {
assert(Values::sValues != nullptr); assert(StaticValues::sValues != nullptr);
return *Values::sValues; return *StaticValues::sValues;
} }
inline CameraCategory& camera() inline CameraCategory& camera()
@ -200,6 +214,18 @@ namespace Settings
{ {
return values().mPostProcessing; return values().mPostProcessing;
} }
template <class T>
SettingValue<T>* find(std::string_view category, std::string_view name)
{
return StaticValues::sIndex->find<T>(category, name);
}
template <class T>
SettingValue<T>& get(std::string_view category, std::string_view name)
{
return StaticValues::sIndex->get<T>(category, name);
}
} }
#endif #endif

@ -335,7 +335,7 @@
<UserString key="SettingType" value="Slider"/> <UserString key="SettingType" value="Slider"/>
<UserString key="SettingCategory" value="Camera"/> <UserString key="SettingCategory" value="Camera"/>
<UserString key="SettingName" value="field of view"/> <UserString key="SettingName" value="field of view"/>
<UserString key="SettingValueType" value="Integer"/> <UserString key="SettingValueType" value="Float"/>
<UserString key="SettingMin" value="30"/> <UserString key="SettingMin" value="30"/>
<UserString key="SettingMax" value="110"/> <UserString key="SettingMax" value="110"/>
<UserString key="SettingLabelWidget" value="FovText"/> <UserString key="SettingLabelWidget" value="FovText"/>
@ -406,7 +406,7 @@
<UserString key="SettingType" value="Slider"/> <UserString key="SettingType" value="Slider"/>
<UserString key="SettingCategory" value="Camera"/> <UserString key="SettingCategory" value="Camera"/>
<UserString key="SettingName" value="viewing distance"/> <UserString key="SettingName" value="viewing distance"/>
<UserString key="SettingValueType" value="Integer"/> <UserString key="SettingValueType" value="Float"/>
<UserString key="SettingMin" value="2500"/> <UserString key="SettingMin" value="2500"/>
<UserString key="SettingMax" value="7168"/> <UserString key="SettingMax" value="7168"/>
<UserString key="SettingLabelWidget" value="RenderDistanceLabel"/> <UserString key="SettingLabelWidget" value="RenderDistanceLabel"/>
@ -577,7 +577,7 @@
<UserString key="SettingMax" value="8192"/> <UserString key="SettingMax" value="8192"/>
<UserString key="SettingCategory" value="Shaders"/> <UserString key="SettingCategory" value="Shaders"/>
<UserString key="SettingName" value="maximum light distance"/> <UserString key="SettingName" value="maximum light distance"/>
<UserString key="SettingValueType" value="Integer"/> <UserString key="SettingValueType" value="Float"/>
<UserString key="SettingLabelWidget" value="MaxLightDistanceText"/> <UserString key="SettingLabelWidget" value="MaxLightDistanceText"/>
<UserString key="SettingLabelCaption" value="#{OMWEngine:LightsMaximumDistance} (%s)"/> <UserString key="SettingLabelCaption" value="#{OMWEngine:LightsMaximumDistance} (%s)"/>
</Widget> </Widget>

Loading…
Cancel
Save