diff --git a/apps/benchmarks/CMakeLists.txt b/apps/benchmarks/CMakeLists.txt index 971a1ecd25..8039f2a3d2 100644 --- a/apps/benchmarks/CMakeLists.txt +++ b/apps/benchmarks/CMakeLists.txt @@ -4,3 +4,4 @@ endif() add_subdirectory(detournavigator) add_subdirectory(esm) +add_subdirectory(settings) diff --git a/apps/benchmarks/settings/CMakeLists.txt b/apps/benchmarks/settings/CMakeLists.txt new file mode 100644 index 0000000000..bc2f8cd44b --- /dev/null +++ b/apps/benchmarks/settings/CMakeLists.txt @@ -0,0 +1,15 @@ +openmw_add_executable(openmw_settings_access_benchmark access.cpp) +target_link_libraries(openmw_settings_access_benchmark benchmark::benchmark components) + +if (UNIX AND NOT APPLE) + target_link_libraries(openmw_settings_access_benchmark ${CMAKE_THREAD_LIBS_INIT}) +endif() + +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC) + target_precompile_headers(openmw_settings_access_benchmark PRIVATE ) +endif() + +if (BUILD_WITH_CODE_COVERAGE) + target_compile_options(openmw_settings_access_benchmark PRIVATE --coverage) + target_link_libraries(openmw_settings_access_benchmark gcov) +endif() diff --git a/apps/benchmarks/settings/access.cpp b/apps/benchmarks/settings/access.cpp new file mode 100644 index 0000000000..468debec91 --- /dev/null +++ b/apps/benchmarks/settings/access.cpp @@ -0,0 +1,86 @@ +#include + +#include +#include +#include + +#include + +#include +#include + +namespace +{ + namespace bpo = boost::program_options; + + bpo::options_description makeOptionsDescription() + { + bpo::options_description result; + auto addOption = result.add_options(); + addOption("help", "print help message"); + Files::ConfigurationManager::addCommonOptions(result); + return result; + } + + void settingsManager(benchmark::State& state) + { + for (auto _ : state) + { + benchmark::DoNotOptimize(Settings::Manager::getFloat("sky blending start", "Fog")); + } + } + + void localStatic(benchmark::State& state) + { + for (auto _ : state) + { + static const float v = Settings::Manager::getFloat("sky blending start", "Fog"); + benchmark::DoNotOptimize(v); + } + } + + void settingsStorage(benchmark::State& state) + { + for (auto _ : state) + { + benchmark::DoNotOptimize(Settings::fog().mSkyBlendingStart.get()); + } + } +} + +BENCHMARK(settingsManager); +BENCHMARK(localStatic); +BENCHMARK(settingsStorage); + +int main(int argc, char* argv[]) +{ + bpo::options_description desc = makeOptionsDescription(); + + bpo::parsed_options options = bpo::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); + bpo::variables_map variables; + + bpo::store(options, variables); + bpo::notify(variables); + + if (variables.find("help") != variables.end()) + { + std::cout << desc << std::endl; + benchmark::Initialize(&argc, argv); + benchmark::Shutdown(); + return 1; + } + + Files::ConfigurationManager config; + + bpo::variables_map composingVariables = Files::separateComposingVariables(variables, desc); + config.readConfiguration(variables, desc); + Files::mergeComposingVariables(variables, composingVariables, desc); + + Settings::Manager::load(config); + + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + benchmark::Shutdown(); + + return 0; +} diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 58f0981e7f..f572b107a1 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -42,7 +42,39 @@ add_component_dir (l10n ) add_component_dir (settings - settings parser + categories + categories/camera + categories/cells + categories/fog + categories/game + categories/general + categories/groundcover + categories/gui + categories/hud + categories/input + categories/lua + categories/map + categories/models + categories/navigator + categories/physics + categories/postprocessing + categories/saves + categories/shaders + categories/shadows + categories/sound + categories/stereo + categories/stereoview + categories/terrain + categories/video + categories/water + categories/windows + parser + sanitizer + sanitizerimpl + settings + settingvalue + shadermanager + values ) add_component_dir (bsa diff --git a/components/detournavigator/settings.cpp b/components/detournavigator/settings.cpp index c39275d468..0470c629e5 100644 --- a/components/detournavigator/settings.cpp +++ b/components/detournavigator/settings.cpp @@ -1,36 +1,29 @@ #include "settings.hpp" #include -#include - -#include +#include namespace DetourNavigator { RecastSettings makeRecastSettingsFromSettingsManager() { - constexpr float epsilon = std::numeric_limits::epsilon(); - RecastSettings result; - result.mBorderSize = std::max(0, ::Settings::Manager::getInt("border size", "Navigator")); - result.mCellHeight = std::max(epsilon, ::Settings::Manager::getFloat("cell height", "Navigator")); - result.mCellSize = std::max(epsilon, ::Settings::Manager::getFloat("cell size", "Navigator")); - result.mDetailSampleDist = std::max(0.0f, ::Settings::Manager::getFloat("detail sample dist", "Navigator")); - result.mDetailSampleMaxError - = std::max(0.0f, ::Settings::Manager::getFloat("detail sample max error", "Navigator")); + result.mBorderSize = ::Settings::navigator().mBorderSize; + result.mCellHeight = ::Settings::navigator().mCellHeight; + result.mCellSize = ::Settings::navigator().mCellSize; + result.mDetailSampleDist = ::Settings::navigator().mDetailSampleDist; + result.mDetailSampleMaxError = ::Settings::navigator().mDetailSampleMaxError; result.mMaxClimb = Constants::sStepSizeUp; - result.mMaxSimplificationError - = std::max(0.0f, ::Settings::Manager::getFloat("max simplification error", "Navigator")); + result.mMaxSimplificationError = ::Settings::navigator().mMaxSimplificationError; result.mMaxSlope = Constants::sMaxSlope; - result.mRecastScaleFactor - = std::max(epsilon, ::Settings::Manager::getFloat("recast scale factor", "Navigator")); + result.mRecastScaleFactor = ::Settings::navigator().mRecastScaleFactor; result.mSwimHeightScale = 0; - result.mMaxEdgeLen = std::max(0, ::Settings::Manager::getInt("max edge len", "Navigator")); - result.mMaxVertsPerPoly = std::max(3, ::Settings::Manager::getInt("max verts per poly", "Navigator")); - result.mRegionMergeArea = std::max(0, ::Settings::Manager::getInt("region merge area", "Navigator")); - result.mRegionMinArea = std::max(0, ::Settings::Manager::getInt("region min area", "Navigator")); - result.mTileSize = std::max(1, ::Settings::Manager::getInt("tile size", "Navigator")); + result.mMaxEdgeLen = ::Settings::navigator().mMaxEdgeLen; + result.mMaxVertsPerPoly = ::Settings::navigator().mMaxVertsPerPoly; + result.mRegionMergeArea = ::Settings::navigator().mRegionMergeArea; + result.mRegionMinArea = ::Settings::navigator().mRegionMinArea; + result.mTileSize = ::Settings::navigator().mTileSize; return result; } @@ -39,12 +32,10 @@ namespace DetourNavigator { DetourSettings result; - result.mMaxNavMeshQueryNodes - = std::clamp(::Settings::Manager::getInt("max nav mesh query nodes", "Navigator"), 1, 65535); - result.mMaxPolys - = std::clamp(::Settings::Manager::getInt("max polygons per tile", "Navigator"), 1, (1 << 22) - 1); - result.mMaxPolygonPathSize = ::Settings::Manager::getSize("max polygon path size", "Navigator"); - result.mMaxSmoothPathSize = ::Settings::Manager::getSize("max smooth path size", "Navigator"); + result.mMaxNavMeshQueryNodes = ::Settings::navigator().mMaxNavMeshQueryNodes; + result.mMaxPolys = ::Settings::navigator().mMaxPolygonsPerTile; + result.mMaxPolygonPathSize = ::Settings::navigator().mMaxPolygonPathSize; + result.mMaxSmoothPathSize = ::Settings::navigator().mMaxSmoothPathSize; return result; } @@ -55,26 +46,20 @@ namespace DetourNavigator result.mRecast = makeRecastSettingsFromSettingsManager(); result.mDetour = makeDetourSettingsFromSettingsManager(); - result.mMaxTilesNumber = std::max(0, ::Settings::Manager::getInt("max tiles number", "Navigator")); - result.mWaitUntilMinDistanceToPlayer - = ::Settings::Manager::getInt("wait until min distance to player", "Navigator"); - result.mAsyncNavMeshUpdaterThreads - = ::Settings::Manager::getSize("async nav mesh updater threads", "Navigator"); - result.mMaxNavMeshTilesCacheSize = ::Settings::Manager::getSize("max nav mesh tiles cache size", "Navigator"); - result.mEnableWriteRecastMeshToFile - = ::Settings::Manager::getBool("enable write recast mesh to file", "Navigator"); - result.mEnableWriteNavMeshToFile = ::Settings::Manager::getBool("enable write nav mesh to file", "Navigator"); - result.mRecastMeshPathPrefix = ::Settings::Manager::getString("recast mesh path prefix", "Navigator"); - result.mNavMeshPathPrefix = ::Settings::Manager::getString("nav mesh path prefix", "Navigator"); - result.mEnableRecastMeshFileNameRevision - = ::Settings::Manager::getBool("enable recast mesh file name revision", "Navigator"); - result.mEnableNavMeshFileNameRevision - = ::Settings::Manager::getBool("enable nav mesh file name revision", "Navigator"); - result.mMinUpdateInterval - = std::chrono::milliseconds(::Settings::Manager::getInt("min update interval ms", "Navigator")); - result.mEnableNavMeshDiskCache = ::Settings::Manager::getBool("enable nav mesh disk cache", "Navigator"); - result.mWriteToNavMeshDb = ::Settings::Manager::getBool("write to navmeshdb", "Navigator"); - result.mMaxDbFileSize = ::Settings::Manager::getUInt64("max navmeshdb file size", "Navigator"); + result.mMaxTilesNumber = ::Settings::navigator().mMaxTilesNumber; + result.mWaitUntilMinDistanceToPlayer = ::Settings::navigator().mWaitUntilMinDistanceToPlayer; + result.mAsyncNavMeshUpdaterThreads = ::Settings::navigator().mAsyncNavMeshUpdaterThreads; + result.mMaxNavMeshTilesCacheSize = ::Settings::navigator().mMaxNavMeshTilesCacheSize; + result.mEnableWriteRecastMeshToFile = ::Settings::navigator().mEnableWriteRecastMeshToFile; + result.mEnableWriteNavMeshToFile = ::Settings::navigator().mEnableWriteNavMeshToFile; + result.mRecastMeshPathPrefix = ::Settings::navigator().mRecastMeshPathPrefix; + result.mNavMeshPathPrefix = ::Settings::navigator().mNavMeshPathPrefix; + result.mEnableRecastMeshFileNameRevision = ::Settings::navigator().mEnableRecastMeshFileNameRevision; + result.mEnableNavMeshFileNameRevision = ::Settings::navigator().mEnableNavMeshFileNameRevision; + result.mMinUpdateInterval = std::chrono::milliseconds(::Settings::navigator().mMinUpdateIntervalMs); + result.mEnableNavMeshDiskCache = ::Settings::navigator().mEnableNavMeshDiskCache; + result.mWriteToNavMeshDb = ::Settings::navigator().mWriteToNavmeshdb; + result.mMaxDbFileSize = ::Settings::navigator().mMaxNavmeshdbFileSize; return result; } diff --git a/components/settings/categories/camera.hpp b/components/settings/categories/camera.hpp new file mode 100644 index 0000000000..d9a2aef75c --- /dev/null +++ b/components/settings/categories/camera.hpp @@ -0,0 +1,31 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_CAMERA_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_CAMERA_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct CameraCategory + { + SettingValue mNearClip{ "Camera", "near clip", makeMaxSanitizerFloat(0.005f) }; + SettingValue mSmallFeatureCulling{ "Camera", "small feature culling" }; + SettingValue mSmallFeatureCullingPixelSize{ "Camera", "small feature culling pixel size", + makeMaxStrictSanitizerFloat(0) }; + SettingValue mViewingDistance{ "Camera", "viewing distance", makeMaxStrictSanitizerFloat(0) }; + SettingValue mFieldOfView{ "Camera", "field of view", makeClampSanitizerFloat(1, 179) }; + SettingValue mFirstPersonFieldOfView{ "Camera", "first person field of view", + makeClampSanitizerFloat(1, 179) }; + SettingValue mReverseZ{ "Camera", "reverse z" }; + }; +} + +#endif diff --git a/components/settings/categories/cells.hpp b/components/settings/categories/cells.hpp new file mode 100644 index 0000000000..c6d7fe05d4 --- /dev/null +++ b/components/settings/categories/cells.hpp @@ -0,0 +1,36 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_CELLS_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_CELLS_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct CellsCategory + { + SettingValue mPreloadEnabled{ "Cells", "preload enabled" }; + SettingValue mPreloadNumThreads{ "Cells", "preload num threads", makeMaxSanitizerInt(1) }; + SettingValue mPreloadExteriorGrid{ "Cells", "preload exterior grid" }; + SettingValue mPreloadFastTravel{ "Cells", "preload fast travel" }; + SettingValue mPreloadDoors{ "Cells", "preload doors" }; + SettingValue mPreloadDistance{ "Cells", "preload distance", makeMaxStrictSanitizerFloat(0) }; + SettingValue mPreloadInstances{ "Cells", "preload instances" }; + SettingValue mPreloadCellCacheMin{ "Cells", "preload cell cache min", makeMaxSanitizerInt(1) }; + SettingValue mPreloadCellCacheMax{ "Cells", "preload cell cache max", makeMaxSanitizerInt(1) }; + SettingValue mPreloadCellExpiryDelay{ "Cells", "preload cell expiry delay", makeMaxSanitizerFloat(0) }; + SettingValue mPredictionTime{ "Cells", "prediction time", makeMaxSanitizerFloat(0) }; + SettingValue mCacheExpiryDelay{ "Cells", "cache expiry delay", makeMaxSanitizerFloat(0) }; + SettingValue mTargetFramerate{ "Cells", "target framerate", makeMaxStrictSanitizerFloat(0) }; + SettingValue mPointersCacheSize{ "Cells", "pointers cache size", makeClampSanitizerInt(40, 1000) }; + }; +} + +#endif diff --git a/components/settings/categories/fog.hpp b/components/settings/categories/fog.hpp new file mode 100644 index 0000000000..c9fe03aca3 --- /dev/null +++ b/components/settings/categories/fog.hpp @@ -0,0 +1,34 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_FOG_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_FOG_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct FogCategory + { + SettingValue mUseDistantFog{ "Fog", "use distant fog" }; + SettingValue mDistantLandFogStart{ "Fog", "distant land fog start" }; + SettingValue mDistantLandFogEnd{ "Fog", "distant land fog end" }; + SettingValue mDistantUnderwaterFogStart{ "Fog", "distant underwater fog start" }; + SettingValue mDistantUnderwaterFogEnd{ "Fog", "distant underwater fog end" }; + SettingValue mDistantInteriorFogStart{ "Fog", "distant interior fog start" }; + SettingValue mDistantInteriorFogEnd{ "Fog", "distant interior fog end" }; + SettingValue mRadialFog{ "Fog", "radial fog" }; + SettingValue mExponentialFog{ "Fog", "exponential fog" }; + SettingValue mSkyBlending{ "Fog", "sky blending" }; + SettingValue mSkyBlendingStart{ "Fog", "sky blending start", makeClampStrictMaxSanitizerFloat(0, 1) }; + SettingValue mSkyRttResolution{ "Fog", "sky rtt resolution" }; + }; +} + +#endif diff --git a/components/settings/categories/game.hpp b/components/settings/categories/game.hpp new file mode 100644 index 0000000000..3d7cc852d8 --- /dev/null +++ b/components/settings/categories/game.hpp @@ -0,0 +1,71 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_GAME_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_GAME_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct GameCategory + { + SettingValue mShowOwned{ "Game", "show owned", makeEnumSanitizerInt({ 0, 1, 2, 3 }) }; + SettingValue mShowProjectileDamage{ "Game", "show projectile damage" }; + SettingValue mShowMeleeInfo{ "Game", "show melee info" }; + SettingValue mShowEnchantChance{ "Game", "show enchant chance" }; + SettingValue mBestAttack{ "Game", "best attack" }; + SettingValue mDifficulty{ "Game", "difficulty", makeClampSanitizerInt(-500, 500) }; + SettingValue mActorsProcessingRange{ "Game", "actors processing range", + makeClampSanitizerInt(3584, 7168) }; + SettingValue mClassicReflectedAbsorbSpellsBehavior{ "Game", "classic reflected absorb spells behavior" }; + SettingValue mClassicCalmSpellsBehavior{ "Game", "classic calm spells behavior" }; + SettingValue mShowEffectDuration{ "Game", "show effect duration" }; + SettingValue mPreventMerchantEquipping{ "Game", "prevent merchant equipping" }; + SettingValue mEnchantedWeaponsAreMagical{ "Game", "enchanted weapons are magical" }; + SettingValue mFollowersAttackOnSight{ "Game", "followers attack on sight" }; + SettingValue mCanLootDuringDeathAnimation{ "Game", "can loot during death animation" }; + SettingValue mRebalanceSoulGemValues{ "Game", "rebalance soul gem values" }; + SettingValue mUseAdditionalAnimSources{ "Game", "use additional anim sources" }; + SettingValue mBarterDispositionChangeIsPermanent{ "Game", "barter disposition change is permanent" }; + SettingValue mStrengthInfluencesHandToHand{ "Game", "strength influences hand to hand", + makeEnumSanitizerInt({ 0, 1, 2 }) }; + SettingValue mWeaponSheathing{ "Game", "weapon sheathing" }; + SettingValue mShieldSheathing{ "Game", "shield sheathing" }; + SettingValue mOnlyAppropriateAmmunitionBypassesResistance{ "Game", + "only appropriate ammunition bypasses resistance" }; + SettingValue mUseMagicItemAnimations{ "Game", "use magic item animations" }; + SettingValue mNormaliseRaceSpeed{ "Game", "normalise race speed" }; + SettingValue mProjectilesEnchantMultiplier{ "Game", "projectiles enchant multiplier", + makeClampSanitizerFloat(0, 1) }; + SettingValue mUncappedDamageFatigue{ "Game", "uncapped damage fatigue" }; + SettingValue mTurnToMovementDirection{ "Game", "turn to movement direction" }; + SettingValue mSmoothMovement{ "Game", "smooth movement" }; + SettingValue mSmoothMovementPlayerTurningDelay{ "Game", "smooth movement player turning delay", + makeMaxSanitizerFloat(0.01f) }; + SettingValue mNPCsAvoidCollisions{ "Game", "NPCs avoid collisions" }; + SettingValue mNPCsGiveWay{ "Game", "NPCs give way" }; + SettingValue mSwimUpwardCorrection{ "Game", "swim upward correction" }; + SettingValue mSwimUpwardCoef{ "Game", "swim upward coef", makeClampSanitizerFloat(-1, 1) }; + SettingValue mTrainersTrainingSkillsBasedOnBaseSkill{ "Game", + "trainers training skills based on base skill" }; + SettingValue mAlwaysAllowStealingFromKnockedOutActors{ "Game", + "always allow stealing from knocked out actors" }; + SettingValue mGraphicHerbalism{ "Game", "graphic herbalism" }; + SettingValue mAllowActorsToFollowOverWaterSurface{ "Game", "allow actors to follow over water surface" }; + SettingValue mDefaultActorPathfindHalfExtents{ "Game", "default actor pathfind half extents", + makeMaxStrictSanitizerVec3f(osg::Vec3f(0, 0, 0)) }; + SettingValue mDayNightSwitches{ "Game", "day night switches" }; + SettingValue mUnarmedCreatureAttacksDamageArmor{ "Game", "unarmed creature attacks damage armor" }; + SettingValue mActorCollisionShapeType{ "Game", "actor collision shape type", + makeEnumSanitizerInt({ 0, 1, 2 }) }; + }; +} + +#endif diff --git a/components/settings/categories/general.hpp b/components/settings/categories/general.hpp new file mode 100644 index 0000000000..405db5167b --- /dev/null +++ b/components/settings/categories/general.hpp @@ -0,0 +1,35 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_GENERAL_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_GENERAL_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct GeneralCategory + { + SettingValue mAnisotropy{ "General", "anisotropy", makeClampSanitizerInt(0, 16) }; + SettingValue mScreenshotFormat{ "General", "screenshot format", + makeEnumSanitizerString({ "jpg", "png", "tga" }) }; + SettingValue mTextureMagFilter{ "General", "texture mag filter", + makeEnumSanitizerString({ "nearest", "linear" }) }; + SettingValue mTextureMinFilter{ "General", "texture min filter", + makeEnumSanitizerString({ "nearest", "linear" }) }; + SettingValue mTextureMipmap{ "General", "texture mipmap", + makeEnumSanitizerString({ "none", "nearest", "linear" }) }; + SettingValue mNotifyOnSavedScreenshot{ "General", "notify on saved screenshot" }; + SettingValue mPreferredLocales{ "General", "preferred locales" }; + SettingValue mLogBufferSize{ "General", "log buffer size" }; + SettingValue mConsoleHistoryBufferSize{ "General", "console history buffer size" }; + }; +} + +#endif diff --git a/components/settings/categories/groundcover.hpp b/components/settings/categories/groundcover.hpp new file mode 100644 index 0000000000..5e90baa4fb --- /dev/null +++ b/components/settings/categories/groundcover.hpp @@ -0,0 +1,27 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_GROUNDCOVER_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_GROUNDCOVER_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct GroundcoverCategory + { + SettingValue mEnabled{ "Groundcover", "enabled" }; + SettingValue mDensity{ "Groundcover", "density", makeClampSanitizerFloat(0, 1) }; + SettingValue mRenderingDistance{ "Groundcover", "rendering distance", makeMaxSanitizerFloat(0) }; + SettingValue mStompMode{ "Groundcover", "stomp mode", makeEnumSanitizerInt({ 0, 1, 2 }) }; + SettingValue mStompIntensity{ "Groundcover", "stomp intensity", makeEnumSanitizerInt({ 0, 1, 2 }) }; + }; +} + +#endif diff --git a/components/settings/categories/gui.hpp b/components/settings/categories/gui.hpp new file mode 100644 index 0000000000..cb2995fb69 --- /dev/null +++ b/components/settings/categories/gui.hpp @@ -0,0 +1,36 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_GUI_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_GUI_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct GUICategory + { + SettingValue mScalingFactor{ "GUI", "scaling factor", makeClampSanitizerFloat(0.5f, 8) }; + SettingValue mFontSize{ "GUI", "font size", makeClampSanitizerInt(12, 18) }; + SettingValue mMenuTransparency{ "GUI", "menu transparency", makeClampSanitizerFloat(0, 1) }; + SettingValue mTooltipDelay{ "GUI", "tooltip delay", makeMaxSanitizerFloat(0) }; + SettingValue mStretchMenuBackground{ "GUI", "stretch menu background" }; + SettingValue mSubtitles{ "GUI", "subtitles" }; + SettingValue mHitFader{ "GUI", "hit fader" }; + SettingValue mWerewolfOverlay{ "GUI", "werewolf overlay" }; + SettingValue mColorBackgroundOwned{ "GUI", "color background owned", makeClampSanitizerFloat(0, 1) }; + SettingValue mColorCrosshairOwned{ "GUI", "color crosshair owned", makeClampSanitizerFloat(0, 1) }; + SettingValue mKeyboardNavigation{ "GUI", "keyboard navigation" }; + SettingValue mColorTopicEnable{ "GUI", "color topic enable" }; + SettingValue mColorTopicSpecific{ "GUI", "color topic specific", makeClampSanitizerFloat(0, 1) }; + SettingValue mColorTopicExhausted{ "GUI", "color topic exhausted", makeClampSanitizerFloat(0, 1) }; + }; +} + +#endif diff --git a/components/settings/categories/hud.hpp b/components/settings/categories/hud.hpp new file mode 100644 index 0000000000..085939512e --- /dev/null +++ b/components/settings/categories/hud.hpp @@ -0,0 +1,23 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_HUD_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_HUD_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct HUDCategory + { + SettingValue mCrosshair{ "HUD", "crosshair" }; + }; +} + +#endif diff --git a/components/settings/categories/input.hpp b/components/settings/categories/input.hpp new file mode 100644 index 0000000000..280279dccb --- /dev/null +++ b/components/settings/categories/input.hpp @@ -0,0 +1,40 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_INPUT_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_INPUT_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct InputCategory + { + SettingValue mGrabCursor{ "Input", "grab cursor" }; + SettingValue mCameraSensitivity{ "Input", "camera sensitivity", makeMaxStrictSanitizerFloat(0) }; + SettingValue mCameraYMultiplier{ "Input", "camera y multiplier", makeMaxStrictSanitizerFloat(0) }; + SettingValue mInvertXAxis{ "Input", "invert x axis" }; + SettingValue mInvertYAxis{ "Input", "invert y axis" }; + SettingValue mEnableController{ "Input", "enable controller" }; + SettingValue mGamepadCursorSpeed{ "Input", "gamepad cursor speed", makeMaxStrictSanitizerFloat(0) }; + SettingValue mJoystickDeadZone{ "Input", "joystick dead zone", makeClampSanitizerFloat(0, 0.5f) }; + SettingValue mEnableGyroscope{ "Input", "enable gyroscope" }; + SettingValue mGyroHorizontalAxis{ "Input", "gyro horizontal axis", + makeEnumSanitizerString({ "x", "y", "z", "-x", "-y", "-z" }) }; + SettingValue mGyroVerticalAxis{ "Input", "gyro vertical axis", + makeEnumSanitizerString({ "x", "y", "z", "-x", "-y", "-z" }) }; + SettingValue mGyroInputThreshold{ "Input", "gyro input threshold", makeMaxSanitizerFloat(0) }; + SettingValue mGyroHorizontalSensitivity{ "Input", "gyro horizontal sensitivity", + makeMaxStrictSanitizerFloat(0) }; + SettingValue mGyroVerticalSensitivity{ "Input", "gyro vertical sensitivity", + makeMaxStrictSanitizerFloat(0) }; + }; +} + +#endif diff --git a/components/settings/categories/lua.hpp b/components/settings/categories/lua.hpp new file mode 100644 index 0000000000..02ef4a4936 --- /dev/null +++ b/components/settings/categories/lua.hpp @@ -0,0 +1,31 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_LUA_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_LUA_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct LuaCategory + { + SettingValue mLuaDebug{ "Lua", "lua debug" }; + SettingValue mLuaNumThreads{ "Lua", "lua num threads", makeEnumSanitizerInt({ 0, 1 }) }; + SettingValue mLuaProfiler{ "Lua", "lua profiler" }; + SettingValue mSmallAllocMaxSize{ "Lua", "small alloc max size" }; + SettingValue mMemoryLimit{ "Lua", "memory limit" }; + SettingValue mLogMemoryUsage{ "Lua", "log memory usage" }; + SettingValue mInstructionLimitPerCall{ "Lua", "instruction limit per call", + makeMaxSanitizerUInt64(1001) }; + SettingValue mGcStepsPerFrame{ "Lua", "gc steps per frame", makeMaxSanitizerInt(0) }; + }; +} + +#endif diff --git a/components/settings/categories/map.hpp b/components/settings/categories/map.hpp new file mode 100644 index 0000000000..9234c60772 --- /dev/null +++ b/components/settings/categories/map.hpp @@ -0,0 +1,30 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_MAP_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_MAP_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct MapCategory + { + SettingValue mGlobalMapCellSize{ "Map", "global map cell size", makeMaxSanitizerInt(1) }; + SettingValue mLocalMapHudWidgetSize{ "Map", "local map hud widget size", makeMaxSanitizerInt(1) }; + SettingValue mLocalMapHudFogOfWar{ "Map", "local map hud fog of war" }; + SettingValue mLocalMapResolution{ "Map", "local map resolution", makeMaxSanitizerInt(1) }; + SettingValue mLocalMapWidgetSize{ "Map", "local map widget size", makeMaxSanitizerInt(1) }; + SettingValue mGlobal{ "Map", "global" }; + SettingValue mAllowZooming{ "Map", "allow zooming" }; + SettingValue mMaxLocalViewingDistance{ "Map", "max local viewing distance", makeMaxSanitizerInt(1) }; + }; +} + +#endif diff --git a/components/settings/categories/models.hpp b/components/settings/categories/models.hpp new file mode 100644 index 0000000000..cd2d403a0c --- /dev/null +++ b/components/settings/categories/models.hpp @@ -0,0 +1,47 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_MODELS_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_MODELS_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct ModelsCategory + { + SettingValue mLoadUnsupportedNifFiles{ "Models", "load unsupported nif files" }; + SettingValue mXbaseanim{ "Models", "xbaseanim" }; + SettingValue mBaseanim{ "Models", "baseanim" }; + SettingValue mXbaseanim1st{ "Models", "xbaseanim1st" }; + SettingValue mBaseanimkna{ "Models", "baseanimkna" }; + SettingValue mBaseanimkna1st{ "Models", "baseanimkna1st" }; + SettingValue mXbaseanimfemale{ "Models", "xbaseanimfemale" }; + SettingValue mBaseanimfemale{ "Models", "baseanimfemale" }; + SettingValue mBaseanimfemale1st{ "Models", "baseanimfemale1st" }; + SettingValue mWolfskin{ "Models", "wolfskin" }; + SettingValue mWolfskin1st{ "Models", "wolfskin1st" }; + SettingValue mXargonianswimkna{ "Models", "xargonianswimkna" }; + SettingValue mXbaseanimkf{ "Models", "xbaseanimkf" }; + SettingValue mXbaseanim1stkf{ "Models", "xbaseanim1stkf" }; + SettingValue mXbaseanimfemalekf{ "Models", "xbaseanimfemalekf" }; + SettingValue mXargonianswimknakf{ "Models", "xargonianswimknakf" }; + SettingValue mSkyatmosphere{ "Models", "skyatmosphere" }; + SettingValue mSkyclouds{ "Models", "skyclouds" }; + SettingValue mSkynight01{ "Models", "skynight01" }; + SettingValue mSkynight02{ "Models", "skynight02" }; + SettingValue mWeatherashcloud{ "Models", "weatherashcloud" }; + SettingValue mWeatherblightcloud{ "Models", "weatherblightcloud" }; + SettingValue mWeathersnow{ "Models", "weathersnow" }; + SettingValue mWeatherblizzard{ "Models", "weatherblizzard" }; + SettingValue mWriteNifDebugLog{ "Models", "write nif debug log" }; + }; +} + +#endif diff --git a/components/settings/categories/navigator.hpp b/components/settings/categories/navigator.hpp new file mode 100644 index 0000000000..56a244f04d --- /dev/null +++ b/components/settings/categories/navigator.hpp @@ -0,0 +1,64 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_NAVIGATOR_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_NAVIGATOR_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct NavigatorCategory + { + SettingValue mEnable{ "Navigator", "enable" }; + SettingValue mRecastScaleFactor{ "Navigator", "recast scale factor", makeMaxStrictSanitizerFloat(0) }; + SettingValue mCellHeight{ "Navigator", "cell height", makeMaxStrictSanitizerFloat(0) }; + SettingValue mCellSize{ "Navigator", "cell size", makeMaxStrictSanitizerFloat(0) }; + SettingValue mDetailSampleDist{ "Navigator", "detail sample dist", + makeEqualOrMaxSanitizerFloat(0, 0.9) }; + SettingValue mDetailSampleMaxError{ "Navigator", "detail sample max error", makeMaxSanitizerFloat(0) }; + SettingValue mMaxSimplificationError{ "Navigator", "max simplification error", + makeMaxSanitizerFloat(0) }; + SettingValue mTileSize{ "Navigator", "tile size", makeMaxSanitizerInt(1) }; + SettingValue mBorderSize{ "Navigator", "border size", makeMaxSanitizerInt(0) }; + SettingValue mMaxEdgeLen{ "Navigator", "max edge len", makeMaxSanitizerInt(0) }; + SettingValue mMaxNavMeshQueryNodes{ "Navigator", "max nav mesh query nodes", + makeClampSanitizerInt(1, 65535) }; + SettingValue mMaxPolygonsPerTile{ "Navigator", "max polygons per tile", + makeClampSanitizerInt(1, 1 << 21) }; + SettingValue mMaxVertsPerPoly{ "Navigator", "max verts per poly", makeMaxSanitizerInt(3) }; + SettingValue mRegionMergeArea{ "Navigator", "region merge area", makeMaxSanitizerInt(0) }; + SettingValue mRegionMinArea{ "Navigator", "region min area", makeMaxSanitizerInt(0) }; + SettingValue mAsyncNavMeshUpdaterThreads{ "Navigator", "async nav mesh updater threads", + makeMaxSanitizerSize(1) }; + SettingValue mMaxNavMeshTilesCacheSize{ "Navigator", "max nav mesh tiles cache size" }; + SettingValue mMaxPolygonPathSize{ "Navigator", "max polygon path size" }; + SettingValue mMaxSmoothPathSize{ "Navigator", "max smooth path size" }; + SettingValue mEnableWriteRecastMeshToFile{ "Navigator", "enable write recast mesh to file" }; + SettingValue mEnableWriteNavMeshToFile{ "Navigator", "enable write nav mesh to file" }; + SettingValue mEnableRecastMeshFileNameRevision{ "Navigator", "enable recast mesh file name revision" }; + SettingValue mEnableNavMeshFileNameRevision{ "Navigator", "enable nav mesh file name revision" }; + SettingValue mRecastMeshPathPrefix{ "Navigator", "recast mesh path prefix" }; + SettingValue mNavMeshPathPrefix{ "Navigator", "nav mesh path prefix" }; + SettingValue mEnableNavMeshRender{ "Navigator", "enable nav mesh render" }; + SettingValue mNavMeshRenderMode{ "Navigator", "nav mesh render mode", + makeEnumSanitizerString({ "area type", "update frequency" }) }; + SettingValue mEnableAgentsPathsRender{ "Navigator", "enable agents paths render" }; + SettingValue mEnableRecastMeshRender{ "Navigator", "enable recast mesh render" }; + SettingValue mMaxTilesNumber{ "Navigator", "max tiles number", makeMaxSanitizerInt(0) }; + SettingValue mMinUpdateIntervalMs{ "Navigator", "min update interval ms", makeMaxSanitizerInt(0) }; + SettingValue mWaitUntilMinDistanceToPlayer{ "Navigator", "wait until min distance to player", + makeMaxSanitizerInt(0) }; + SettingValue mEnableNavMeshDiskCache{ "Navigator", "enable nav mesh disk cache" }; + SettingValue mWriteToNavmeshdb{ "Navigator", "write to navmeshdb" }; + SettingValue mMaxNavmeshdbFileSize{ "Navigator", "max navmeshdb file size" }; + }; +} + +#endif diff --git a/components/settings/categories/physics.hpp b/components/settings/categories/physics.hpp new file mode 100644 index 0000000000..db02f72a98 --- /dev/null +++ b/components/settings/categories/physics.hpp @@ -0,0 +1,25 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_PHYSICS_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_PHYSICS_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct PhysicsCategory + { + SettingValue mAsyncNumThreads{ "Physics", "async num threads", makeMaxSanitizerInt(0) }; + SettingValue mLineofsightKeepInactiveCache{ "Physics", "lineofsight keep inactive cache", + makeMaxSanitizerInt(-1) }; + }; +} + +#endif diff --git a/components/settings/categories/postprocessing.hpp b/components/settings/categories/postprocessing.hpp new file mode 100644 index 0000000000..327ea95df4 --- /dev/null +++ b/components/settings/categories/postprocessing.hpp @@ -0,0 +1,27 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_POSTPROCESSING_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_POSTPROCESSING_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct PostProcessingCategory + { + SettingValue mEnabled{ "Post Processing", "enabled" }; + SettingValue mChain{ "Post Processing", "chain" }; + SettingValue mAutoExposureSpeed{ "Post Processing", "auto exposure speed", + makeMaxStrictSanitizerFloat(0.0001f) }; + SettingValue mTransparentPostpass{ "Post Processing", "transparent postpass" }; + }; +} + +#endif diff --git a/components/settings/categories/saves.hpp b/components/settings/categories/saves.hpp new file mode 100644 index 0000000000..ecaf93fd20 --- /dev/null +++ b/components/settings/categories/saves.hpp @@ -0,0 +1,26 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SAVES_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SAVES_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct SavesCategory + { + SettingValue mCharacter{ "Saves", "character" }; + SettingValue mAutosave{ "Saves", "autosave" }; + SettingValue mTimeplayed{ "Saves", "timeplayed" }; + SettingValue mMaxQuicksaves{ "Saves", "max quicksaves", makeMaxSanitizerInt(1) }; + }; +} + +#endif diff --git a/components/settings/categories/shaders.hpp b/components/settings/categories/shaders.hpp new file mode 100644 index 0000000000..3e04793c01 --- /dev/null +++ b/components/settings/categories/shaders.hpp @@ -0,0 +1,49 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SHADERS_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SHADERS_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct ShadersCategory + { + SettingValue mForceShaders{ "Shaders", "force shaders" }; + SettingValue mForcePerPixelLighting{ "Shaders", "force per pixel lighting" }; + SettingValue mClampLighting{ "Shaders", "clamp lighting" }; + SettingValue mAutoUseObjectNormalMaps{ "Shaders", "auto use object normal maps" }; + SettingValue mAutoUseObjectSpecularMaps{ "Shaders", "auto use object specular maps" }; + SettingValue mAutoUseTerrainNormalMaps{ "Shaders", "auto use terrain normal maps" }; + SettingValue mAutoUseTerrainSpecularMaps{ "Shaders", "auto use terrain specular maps" }; + SettingValue mNormalMapPattern{ "Shaders", "normal map pattern" }; + SettingValue mNormalHeightMapPattern{ "Shaders", "normal height map pattern" }; + SettingValue mSpecularMapPattern{ "Shaders", "specular map pattern" }; + SettingValue mTerrainSpecularMapPattern{ "Shaders", "terrain specular map pattern" }; + SettingValue mApplyLightingToEnvironmentMaps{ "Shaders", "apply lighting to environment maps" }; + SettingValue mLightingMethod{ "Shaders", "lighting method", + makeEnumSanitizerString({ "legacy", "shaders compatibility", "shaders" }) }; + SettingValue mLightBoundsMultiplier{ "Shaders", "light bounds multiplier", + makeClampSanitizerFloat(0, 5) }; + SettingValue mMaximumLightDistance{ "Shaders", "maximum light distance" }; + SettingValue mLightFadeStart{ "Shaders", "light fade start", makeClampSanitizerFloat(0, 1) }; + SettingValue mMaxLights{ "Shaders", "max lights", makeClampSanitizerInt(2, 64) }; + SettingValue mMinimumInteriorBrightness{ "Shaders", "minimum interior brightness", + makeClampSanitizerFloat(0, 1) }; + SettingValue mAntialiasAlphaTest{ "Shaders", "antialias alpha test" }; + SettingValue mAdjustCoverageForAlphaTest{ "Shaders", "adjust coverage for alpha test" }; + SettingValue mSoftParticles{ "Shaders", "soft particles" }; + SettingValue mWeatherParticleOcclusion{ "Shaders", "weather particle occlusion" }; + SettingValue mWeatherParticleOcclusionSmallFeatureCullingPixelSize{ "Shaders", + "weather particle occlusion small feature culling pixel size" }; + }; +} + +#endif diff --git a/components/settings/categories/shadows.hpp b/components/settings/categories/shadows.hpp new file mode 100644 index 0000000000..111f3ae5b4 --- /dev/null +++ b/components/settings/categories/shadows.hpp @@ -0,0 +1,46 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SHADOWS_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SHADOWS_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct ShadowsCategory + { + SettingValue mEnableShadows{ "Shadows", "enable shadows" }; + SettingValue mNumberOfShadowMaps{ "Shadows", "number of shadow maps", makeClampSanitizerInt(1, 8) }; + SettingValue mMaximumShadowMapDistance{ "Shadows", "maximum shadow map distance" }; + SettingValue mShadowFadeStart{ "Shadows", "shadow fade start", makeClampSanitizerFloat(0, 1) }; + SettingValue mAllowShadowMapOverlap{ "Shadows", "allow shadow map overlap" }; + SettingValue mSplitPointUniformLogarithmicRatio{ "Shadows", "split point uniform logarithmic ratio", + makeClampSanitizerFloat(0, 1) }; + SettingValue mSplitPointBias{ "Shadows", "split point bias" }; + SettingValue mEnableDebugHud{ "Shadows", "enable debug hud" }; + SettingValue mEnableDebugOverlay{ "Shadows", "enable debug overlay" }; + SettingValue mComputeSceneBounds{ "Shadows", "compute scene bounds", + makeEnumSanitizerString({ "primitives", "bounds", "none" }) }; + SettingValue mShadowMapResolution{ "Shadows", "shadow map resolution" }; + SettingValue mMinimumLispsmNearFarRatio{ "Shadows", "minimum lispsm near far ratio", + makeMaxStrictSanitizerFloat(0) }; + SettingValue mPolygonOffsetFactor{ "Shadows", "polygon offset factor" }; + SettingValue mPolygonOffsetUnits{ "Shadows", "polygon offset units" }; + SettingValue mNormalOffsetDistance{ "Shadows", "normal offset distance" }; + SettingValue mUseFrontFaceCulling{ "Shadows", "use front face culling" }; + SettingValue mActorShadows{ "Shadows", "actor shadows" }; + SettingValue mPlayerShadows{ "Shadows", "player shadows" }; + SettingValue mTerrainShadows{ "Shadows", "terrain shadows" }; + SettingValue mObjectShadows{ "Shadows", "object shadows" }; + SettingValue mEnableIndoorShadows{ "Shadows", "enable indoor shadows" }; + }; +} + +#endif diff --git a/components/settings/categories/sound.hpp b/components/settings/categories/sound.hpp new file mode 100644 index 0000000000..f8cb59a43a --- /dev/null +++ b/components/settings/categories/sound.hpp @@ -0,0 +1,32 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SOUND_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SOUND_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct SoundCategory + { + SettingValue mDevice{ "Sound", "device" }; + SettingValue mMasterVolume{ "Sound", "master volume", makeClampSanitizerFloat(0, 1) }; + SettingValue mFootstepsVolume{ "Sound", "footsteps volume", makeClampSanitizerFloat(0, 1) }; + SettingValue mMusicVolume{ "Sound", "music volume", makeClampSanitizerFloat(0, 1) }; + SettingValue mSfxVolume{ "Sound", "sfx volume", makeClampSanitizerFloat(0, 1) }; + SettingValue mVoiceVolume{ "Sound", "voice volume", makeClampSanitizerFloat(0, 1) }; + SettingValue mBufferCacheMin{ "Sound", "buffer cache min", makeMaxSanitizerInt(1) }; + SettingValue mBufferCacheMax{ "Sound", "buffer cache max", makeMaxSanitizerInt(1) }; + SettingValue mHrtfEnable{ "Sound", "hrtf enable", makeEnumSanitizerInt({ -1, 0, 1 }) }; + SettingValue mHrtf{ "Sound", "hrtf" }; + }; +} + +#endif diff --git a/components/settings/categories/stereo.hpp b/components/settings/categories/stereo.hpp new file mode 100644 index 0000000000..4c24e5762f --- /dev/null +++ b/components/settings/categories/stereo.hpp @@ -0,0 +1,28 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_STEREO_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_STEREO_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct StereoCategory + { + SettingValue mStereoEnabled{ "Stereo", "stereo enabled" }; + SettingValue mMultiview{ "Stereo", "multiview" }; + SettingValue mSharedShadowMaps{ "Stereo", "shared shadow maps" }; + SettingValue mAllowDisplayListsForMultiview{ "Stereo", "allow display lists for multiview" }; + SettingValue mUseCustomView{ "Stereo", "use custom view" }; + SettingValue mUseCustomEyeResolution{ "Stereo", "use custom eye resolution" }; + }; +} + +#endif diff --git a/components/settings/categories/stereoview.hpp b/components/settings/categories/stereoview.hpp new file mode 100644 index 0000000000..492ea30d47 --- /dev/null +++ b/components/settings/categories/stereoview.hpp @@ -0,0 +1,62 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_STEREOVIEW_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_STEREOVIEW_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct StereoViewCategory + { + SettingValue mEyeResolutionX{ "Stereo View", "eye resolution x", makeMaxSanitizerInt(1) }; + SettingValue mEyeResolutionY{ "Stereo View", "eye resolution y", makeMaxSanitizerInt(1) }; + SettingValue mLeftEyeOffsetX{ "Stereo View", "left eye offset x" }; + SettingValue mLeftEyeOffsetY{ "Stereo View", "left eye offset y" }; + SettingValue mLeftEyeOffsetZ{ "Stereo View", "left eye offset z" }; + SettingValue mLeftEyeOrientationX{ "Stereo View", "left eye orientation x", + makeClampSanitizerDouble(-1, 1) }; + SettingValue mLeftEyeOrientationY{ "Stereo View", "left eye orientation y", + makeClampSanitizerDouble(-1, 1) }; + SettingValue mLeftEyeOrientationZ{ "Stereo View", "left eye orientation z", + makeClampSanitizerDouble(-1, 1) }; + SettingValue mLeftEyeOrientationW{ "Stereo View", "left eye orientation w", + makeClampSanitizerDouble(-1, 1) }; + SettingValue mLeftEyeFovLeft{ "Stereo View", "left eye fov left", + makeClampSanitizerDouble(-osg::PI, osg::PI) }; + SettingValue mLeftEyeFovRight{ "Stereo View", "left eye fov right", + makeClampSanitizerDouble(-osg::PI, osg::PI) }; + SettingValue mLeftEyeFovUp{ "Stereo View", "left eye fov up", + makeClampSanitizerDouble(-osg::PI, osg::PI) }; + SettingValue mLeftEyeFovDown{ "Stereo View", "left eye fov down", + makeClampSanitizerDouble(-osg::PI, osg::PI) }; + SettingValue mRightEyeOffsetX{ "Stereo View", "right eye offset x" }; + SettingValue mRightEyeOffsetY{ "Stereo View", "right eye offset y" }; + SettingValue mRightEyeOffsetZ{ "Stereo View", "right eye offset z" }; + SettingValue mRightEyeOrientationX{ "Stereo View", "right eye orientation x", + makeClampSanitizerDouble(-1, 1) }; + SettingValue mRightEyeOrientationY{ "Stereo View", "right eye orientation y", + makeClampSanitizerDouble(-1, 1) }; + SettingValue mRightEyeOrientationZ{ "Stereo View", "right eye orientation z", + makeClampSanitizerDouble(-1, 1) }; + SettingValue mRightEyeOrientationW{ "Stereo View", "right eye orientation w", + makeClampSanitizerDouble(-1, 1) }; + SettingValue mRightEyeFovLeft{ "Stereo View", "right eye fov left", + makeClampSanitizerDouble(-osg::PI, osg::PI) }; + SettingValue mRightEyeFovRight{ "Stereo View", "right eye fov right", + makeClampSanitizerDouble(-osg::PI, osg::PI) }; + SettingValue mRightEyeFovUp{ "Stereo View", "right eye fov up", + makeClampSanitizerDouble(-osg::PI, osg::PI) }; + SettingValue mRightEyeFovDown{ "Stereo View", "right eye fov down", + makeClampSanitizerDouble(-osg::PI, osg::PI) }; + }; +} + +#endif diff --git a/components/settings/categories/terrain.hpp b/components/settings/categories/terrain.hpp new file mode 100644 index 0000000000..6c8d1b035c --- /dev/null +++ b/components/settings/categories/terrain.hpp @@ -0,0 +1,39 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_TERRAIN_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_TERRAIN_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct TerrainCategory + { + SettingValue mDistantTerrain{ "Terrain", "distant terrain" }; + SettingValue mLodFactor{ "Terrain", "lod factor", makeMaxStrictSanitizerFloat(0) }; + SettingValue mVertexLodMod{ "Terrain", "vertex lod mod" }; + SettingValue mCompositeMapLevel{ "Terrain", "composite map level", makeMaxSanitizerInt(-3) }; + SettingValue mCompositeMapResolution{ "Terrain", "composite map resolution", makeMaxSanitizerInt(1) }; + SettingValue mMaxCompositeGeometrySize{ "Terrain", "max composite geometry size", + makeMaxSanitizerFloat(1) }; + SettingValue mDebugChunks{ "Terrain", "debug chunks" }; + SettingValue mObjectPaging{ "Terrain", "object paging" }; + SettingValue mObjectPagingActiveGrid{ "Terrain", "object paging active grid" }; + SettingValue mObjectPagingMergeFactor{ "Terrain", "object paging merge factor", + makeMaxStrictSanitizerFloat(0) }; + SettingValue mObjectPagingMinSize{ "Terrain", "object paging min size", makeMaxStrictSanitizerFloat(0) }; + SettingValue mObjectPagingMinSizeMergeFactor{ "Terrain", "object paging min size merge factor", + makeMaxStrictSanitizerFloat(0) }; + SettingValue mObjectPagingMinSizeCostMultiplier{ "Terrain", "object paging min size cost multiplier", + makeMaxStrictSanitizerFloat(0) }; + }; +} + +#endif diff --git a/components/settings/categories/video.hpp b/components/settings/categories/video.hpp new file mode 100644 index 0000000000..430785f804 --- /dev/null +++ b/components/settings/categories/video.hpp @@ -0,0 +1,34 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_VIDEO_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_VIDEO_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct VideoCategory + { + SettingValue mResolutionX{ "Video", "resolution x", makeMaxSanitizerInt(1) }; + SettingValue mResolutionY{ "Video", "resolution y", makeMaxSanitizerInt(1) }; + SettingValue mWindowMode{ "Video", "window mode", makeEnumSanitizerInt({ 0, 1, 2 }) }; + SettingValue mScreen{ "Video", "screen", makeMaxSanitizerInt(0) }; + SettingValue mMinimizeOnFocusLoss{ "Video", "minimize on focus loss" }; + SettingValue mWindowBorder{ "Video", "window border" }; + SettingValue mAntialiasing{ "Video", "antialiasing", makeEnumSanitizerInt({ 0, 2, 4, 8, 16 }) }; + SettingValue mVsyncMode{ "Video", "vsync mode", makeEnumSanitizerInt({ 0, 1, 2 }) }; + SettingValue mFramerateLimit{ "Video", "framerate limit", makeMaxSanitizerFloat(0) }; + SettingValue mContrast{ "Video", "contrast", makeMaxStrictSanitizerFloat(0) }; + SettingValue mGamma{ "Video", "gamma", makeMaxStrictSanitizerFloat(0) }; + SettingValue mScreenshotType{ "Video", "screenshot type" }; + }; +} + +#endif diff --git a/components/settings/categories/water.hpp b/components/settings/categories/water.hpp new file mode 100644 index 0000000000..97c466bc61 --- /dev/null +++ b/components/settings/categories/water.hpp @@ -0,0 +1,30 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_WATER_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_WATER_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct WaterCategory + { + SettingValue mShader{ "Water", "shader" }; + SettingValue mRttSize{ "Water", "rtt size", makeMaxSanitizerInt(1) }; + SettingValue mRefraction{ "Water", "refraction" }; + SettingValue mReflectionDetail{ "Water", "reflection detail", makeEnumSanitizerInt({ 0, 1, 2, 3, 4, 5 }) }; + SettingValue mRainRippleDetail{ "Water", "rain ripple detail", makeEnumSanitizerInt({ 0, 1, 2 }) }; + SettingValue mSmallFeatureCullingPixelSize{ "Water", "small feature culling pixel size", + makeMaxStrictSanitizerFloat(0) }; + SettingValue mRefractionScale{ "Water", "refraction scale", makeClampSanitizerFloat(0, 1) }; + }; +} + +#endif diff --git a/components/settings/categories/windows.hpp b/components/settings/categories/windows.hpp new file mode 100644 index 0000000000..f472166ab5 --- /dev/null +++ b/components/settings/categories/windows.hpp @@ -0,0 +1,165 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_WINDOWS_H +#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_WINDOWS_H + +#include "components/settings/sanitizerimpl.hpp" +#include "components/settings/settingvalue.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace Settings +{ + struct WindowsCategory + { + SettingValue mStatsX{ "Windows", "stats x" }; + SettingValue mStatsY{ "Windows", "stats y" }; + SettingValue mStatsW{ "Windows", "stats w" }; + SettingValue mStatsH{ "Windows", "stats h" }; + SettingValue mStatsMaximizedX{ "Windows", "stats maximized x" }; + SettingValue mStatsMaximizedY{ "Windows", "stats maximized y" }; + SettingValue mStatsMaximizedW{ "Windows", "stats maximized w" }; + SettingValue mStatsMaximizedH{ "Windows", "stats maximized h" }; + SettingValue mStatsPin{ "Windows", "stats pin" }; + SettingValue mStatsHidden{ "Windows", "stats hidden" }; + SettingValue mStatsMaximized{ "Windows", "stats maximized" }; + SettingValue mSpellsX{ "Windows", "spells x" }; + SettingValue mSpellsY{ "Windows", "spells y" }; + SettingValue mSpellsW{ "Windows", "spells w" }; + SettingValue mSpellsH{ "Windows", "spells h" }; + SettingValue mSpellsMaximizedX{ "Windows", "spells maximized x" }; + SettingValue mSpellsMaximizedY{ "Windows", "spells maximized y" }; + SettingValue mSpellsMaximizedW{ "Windows", "spells maximized w" }; + SettingValue mSpellsMaximizedH{ "Windows", "spells maximized h" }; + SettingValue mSpellsPin{ "Windows", "spells pin" }; + SettingValue mSpellsHidden{ "Windows", "spells hidden" }; + SettingValue mSpellsMaximized{ "Windows", "spells maximized" }; + SettingValue mMapX{ "Windows", "map x" }; + SettingValue mMapY{ "Windows", "map y" }; + SettingValue mMapW{ "Windows", "map w" }; + SettingValue mMapH{ "Windows", "map h" }; + SettingValue mMapMaximizedX{ "Windows", "map maximized x" }; + SettingValue mMapMaximizedY{ "Windows", "map maximized y" }; + SettingValue mMapMaximizedW{ "Windows", "map maximized w" }; + SettingValue mMapMaximizedH{ "Windows", "map maximized h" }; + SettingValue mMapPin{ "Windows", "map pin" }; + SettingValue mMapHidden{ "Windows", "map hidden" }; + SettingValue mMapMaximized{ "Windows", "map maximized" }; + SettingValue mInventoryX{ "Windows", "inventory x" }; + SettingValue mInventoryY{ "Windows", "inventory y" }; + SettingValue mInventoryW{ "Windows", "inventory w" }; + SettingValue mInventoryH{ "Windows", "inventory h" }; + SettingValue mInventoryMaximizedX{ "Windows", "inventory maximized x" }; + SettingValue mInventoryMaximizedY{ "Windows", "inventory maximized y" }; + SettingValue mInventoryMaximizedW{ "Windows", "inventory maximized w" }; + SettingValue mInventoryMaximizedH{ "Windows", "inventory maximized h" }; + SettingValue mInventoryPin{ "Windows", "inventory pin" }; + SettingValue mInventoryHidden{ "Windows", "inventory hidden" }; + SettingValue mInventoryMaximized{ "Windows", "inventory maximized" }; + SettingValue mInventoryContainerX{ "Windows", "inventory container x" }; + SettingValue mInventoryContainerY{ "Windows", "inventory container y" }; + SettingValue mInventoryContainerW{ "Windows", "inventory container w" }; + SettingValue mInventoryContainerH{ "Windows", "inventory container h" }; + SettingValue mInventoryContainerMaximizedX{ "Windows", "inventory container maximized x" }; + SettingValue mInventoryContainerMaximizedY{ "Windows", "inventory container maximized y" }; + SettingValue mInventoryContainerMaximizedW{ "Windows", "inventory container maximized w" }; + SettingValue mInventoryContainerMaximizedH{ "Windows", "inventory container maximized h" }; + SettingValue mInventoryContainerMaximized{ "Windows", "inventory container maximized" }; + SettingValue mInventoryBarterX{ "Windows", "inventory barter x" }; + SettingValue mInventoryBarterY{ "Windows", "inventory barter y" }; + SettingValue mInventoryBarterW{ "Windows", "inventory barter w" }; + SettingValue mInventoryBarterH{ "Windows", "inventory barter h" }; + SettingValue mInventoryBarterMaximizedX{ "Windows", "inventory barter maximized x" }; + SettingValue mInventoryBarterMaximizedY{ "Windows", "inventory barter maximized y" }; + SettingValue mInventoryBarterMaximizedW{ "Windows", "inventory barter maximized w" }; + SettingValue mInventoryBarterMaximizedH{ "Windows", "inventory barter maximized h" }; + SettingValue mInventoryBarterMaximized{ "Windows", "inventory barter maximized" }; + SettingValue mInventoryCompanionX{ "Windows", "inventory companion x" }; + SettingValue mInventoryCompanionY{ "Windows", "inventory companion y" }; + SettingValue mInventoryCompanionW{ "Windows", "inventory companion w" }; + SettingValue mInventoryCompanionH{ "Windows", "inventory companion h" }; + SettingValue mInventoryCompanionMaximizedX{ "Windows", "inventory companion maximized x" }; + SettingValue mInventoryCompanionMaximizedY{ "Windows", "inventory companion maximized y" }; + SettingValue mInventoryCompanionMaximizedW{ "Windows", "inventory companion maximized w" }; + SettingValue mInventoryCompanionMaximizedH{ "Windows", "inventory companion maximized h" }; + SettingValue mInventoryCompanionMaximized{ "Windows", "inventory companion maximized" }; + SettingValue mDialogueX{ "Windows", "dialogue x" }; + SettingValue mDialogueY{ "Windows", "dialogue y" }; + SettingValue mDialogueW{ "Windows", "dialogue w" }; + SettingValue mDialogueH{ "Windows", "dialogue h" }; + SettingValue mDialogueMaximizedX{ "Windows", "dialogue maximized x" }; + SettingValue mDialogueMaximizedY{ "Windows", "dialogue maximized y" }; + SettingValue mDialogueMaximizedW{ "Windows", "dialogue maximized w" }; + SettingValue mDialogueMaximizedH{ "Windows", "dialogue maximized h" }; + SettingValue mDialogueMaximized{ "Windows", "dialogue maximized" }; + SettingValue mAlchemyX{ "Windows", "alchemy x" }; + SettingValue mAlchemyY{ "Windows", "alchemy y" }; + SettingValue mAlchemyW{ "Windows", "alchemy w" }; + SettingValue mAlchemyH{ "Windows", "alchemy h" }; + SettingValue mAlchemyMaximizedX{ "Windows", "alchemy maximized x" }; + SettingValue mAlchemyMaximizedY{ "Windows", "alchemy maximized y" }; + SettingValue mAlchemyMaximizedW{ "Windows", "alchemy maximized w" }; + SettingValue mAlchemyMaximizedH{ "Windows", "alchemy maximized h" }; + SettingValue mAlchemyMaximized{ "Windows", "alchemy maximized" }; + SettingValue mConsoleX{ "Windows", "console x" }; + SettingValue mConsoleY{ "Windows", "console y" }; + SettingValue mConsoleW{ "Windows", "console w" }; + SettingValue mConsoleH{ "Windows", "console h" }; + SettingValue mConsoleMaximizedX{ "Windows", "console maximized x" }; + SettingValue mConsoleMaximizedY{ "Windows", "console maximized y" }; + SettingValue mConsoleMaximizedW{ "Windows", "console maximized w" }; + SettingValue mConsoleMaximizedH{ "Windows", "console maximized h" }; + SettingValue mConsoleMaximized{ "Windows", "console maximized" }; + SettingValue mContainerX{ "Windows", "container x" }; + SettingValue mContainerY{ "Windows", "container y" }; + SettingValue mContainerW{ "Windows", "container w" }; + SettingValue mContainerH{ "Windows", "container h" }; + SettingValue mContainerMaximizedX{ "Windows", "container maximized x" }; + SettingValue mContainerMaximizedY{ "Windows", "container maximized y" }; + SettingValue mContainerMaximizedW{ "Windows", "container maximized w" }; + SettingValue mContainerMaximizedH{ "Windows", "container maximized h" }; + SettingValue mContainerMaximized{ "Windows", "container maximized" }; + SettingValue mBarterX{ "Windows", "barter x" }; + SettingValue mBarterY{ "Windows", "barter y" }; + SettingValue mBarterW{ "Windows", "barter w" }; + SettingValue mBarterH{ "Windows", "barter h" }; + SettingValue mBarterMaximizedX{ "Windows", "barter maximized x" }; + SettingValue mBarterMaximizedY{ "Windows", "barter maximized y" }; + SettingValue mBarterMaximizedW{ "Windows", "barter maximized w" }; + SettingValue mBarterMaximizedH{ "Windows", "barter maximized h" }; + SettingValue mBarterMaximized{ "Windows", "barter maximized" }; + SettingValue mCompanionX{ "Windows", "companion x" }; + SettingValue mCompanionY{ "Windows", "companion y" }; + SettingValue mCompanionW{ "Windows", "companion w" }; + SettingValue mCompanionH{ "Windows", "companion h" }; + SettingValue mCompanionMaximizedX{ "Windows", "companion maximized x" }; + SettingValue mCompanionMaximizedY{ "Windows", "companion maximized y" }; + SettingValue mCompanionMaximizedW{ "Windows", "companion maximized w" }; + SettingValue mCompanionMaximizedH{ "Windows", "companion maximized h" }; + SettingValue mCompanionMaximized{ "Windows", "companion maximized" }; + SettingValue mSettingsX{ "Windows", "settings x" }; + SettingValue mSettingsY{ "Windows", "settings y" }; + SettingValue mSettingsW{ "Windows", "settings w" }; + SettingValue mSettingsH{ "Windows", "settings h" }; + SettingValue mSettingsMaximizedX{ "Windows", "settings maximized x" }; + SettingValue mSettingsMaximizedY{ "Windows", "settings maximized y" }; + SettingValue mSettingsMaximizedW{ "Windows", "settings maximized w" }; + SettingValue mSettingsMaximizedH{ "Windows", "settings maximized h" }; + SettingValue mSettingsMaximized{ "Windows", "settings maximized" }; + SettingValue mPostprocessorH{ "Windows", "postprocessor h" }; + SettingValue mPostprocessorW{ "Windows", "postprocessor w" }; + SettingValue mPostprocessorX{ "Windows", "postprocessor x" }; + SettingValue mPostprocessorY{ "Windows", "postprocessor y" }; + SettingValue mPostprocessorMaximizedX{ "Windows", "postprocessor maximized x" }; + SettingValue mPostprocessorMaximizedY{ "Windows", "postprocessor maximized y" }; + SettingValue mPostprocessorMaximizedW{ "Windows", "postprocessor maximized w" }; + SettingValue mPostprocessorMaximizedH{ "Windows", "postprocessor maximized h" }; + SettingValue mPostprocessorMaximized{ "Windows", "postprocessor maximized" }; + }; +} + +#endif diff --git a/components/settings/sanitizer.hpp b/components/settings/sanitizer.hpp new file mode 100644 index 0000000000..f8ef7ba3df --- /dev/null +++ b/components/settings/sanitizer.hpp @@ -0,0 +1,15 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_SANITIZER_H +#define OPENMW_COMPONENTS_SETTINGS_SANITIZER_H + +namespace Settings +{ + template + struct Sanitizer + { + virtual ~Sanitizer() = default; + + virtual T apply(const T& value) const = 0; + }; +} + +#endif diff --git a/components/settings/sanitizerimpl.cpp b/components/settings/sanitizerimpl.cpp new file mode 100644 index 0000000000..bba08d86db --- /dev/null +++ b/components/settings/sanitizerimpl.cpp @@ -0,0 +1,210 @@ +#include "sanitizerimpl.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Settings +{ + namespace + { + template + struct Max final : Sanitizer + { + T mMax; + + explicit Max(const T& max) + : mMax(max) + { + } + + T apply(const T& value) const override { return std::max(value, mMax); } + }; + + template + struct MaxStrict final : Sanitizer + { + static_assert(std::is_floating_point_v); + + T mMax; + + explicit MaxStrict(const T& max) + : mMax(std::nextafter(max, std::numeric_limits::max())) + { + } + + T apply(const T& value) const override { return std::max(value, mMax); } + }; + + template <> + struct MaxStrict final : Sanitizer + { + osg::Vec3f mMax; + + explicit MaxStrict(const osg::Vec3f& max) + : mMax(std::nextafter(max.x(), std::numeric_limits::max()), + std::nextafter(max.y(), std::numeric_limits::max()), + std::nextafter(max.z(), std::numeric_limits::max())) + { + } + + osg::Vec3f apply(const osg::Vec3f& value) const override + { + return osg::Vec3f( + std::max(value.x(), mMax.x()), std::max(value.y(), mMax.y()), std::max(value.z(), mMax.z())); + } + }; + + template + struct Clamp final : Sanitizer + { + T mMin; + T mMax; + + explicit Clamp(const T& min, const T& max) + : mMin(min) + , mMax(max) + { + } + + T apply(const T& value) const override { return std::clamp(value, mMin, mMax); } + }; + + template + auto getPrev(const T& value) -> std::enable_if_t, T> + { + assert(value > -std::numeric_limits::max()); + return std::nextafter(value, -std::numeric_limits::max()); + } + + template + struct ClampStrictMax final : Sanitizer + { + T mMin; + T mMax; + + explicit ClampStrictMax(const T& min, const T& max) + : mMin(min) + , mMax(getPrev(max)) + { + } + + T apply(const T& value) const override { return std::clamp(value, mMin, mMax); } + }; + + template + struct Enum final : Sanitizer + { + std::vector mValues; + + explicit Enum(std::initializer_list value) + : mValues(std::make_move_iterator(value.begin()), std::make_move_iterator(value.end())) + { + } + + T apply(const T& value) const override + { + if (std::find(mValues.begin(), mValues.end(), value) == mValues.end()) + { + std::ostringstream message; + message << "Invalid enum value: " << value; + throw std::runtime_error(message.str()); + } + return value; + } + }; + + template + struct EqualOrMax final : Sanitizer + { + T mEqual; + T mMax; + + explicit EqualOrMax(const T& equal, const T& max) + : mEqual(equal) + , mMax(max) + { + } + + T apply(const T& value) const override + { + if (value == mEqual) + return value; + return std::max(value, mMax); + } + }; + } + + std::unique_ptr> makeMaxSanitizerFloat(float max) + { + return std::make_unique>(max); + } + + std::unique_ptr> makeMaxSanitizerInt(int max) + { + return std::make_unique>(max); + } + + std::unique_ptr> makeMaxSanitizerSize(std::size_t max) + { + return std::make_unique>(max); + } + + std::unique_ptr> makeMaxSanitizerUInt64(std::uint64_t max) + { + return std::make_unique>(max); + } + + std::unique_ptr> makeMaxStrictSanitizerFloat(float max) + { + return std::make_unique>(max); + } + + std::unique_ptr> makeMaxStrictSanitizerVec3f(const osg::Vec3f& max) + { + return std::make_unique>(max); + } + + std::unique_ptr> makeClampSanitizerFloat(float min, float max) + { + return std::make_unique>(min, max); + } + + std::unique_ptr> makeClampSanitizerDouble(double min, double max) + { + return std::make_unique>(min, max); + } + + std::unique_ptr> makeClampSanitizerInt(int min, int max) + { + return std::make_unique>(min, max); + } + + std::unique_ptr> makeClampStrictMaxSanitizerFloat(float min, float max) + { + return std::make_unique>(min, max); + } + + std::unique_ptr> makeEnumSanitizerInt(std::initializer_list values) + { + return std::make_unique>(values); + } + + std::unique_ptr> makeEnumSanitizerString(std::initializer_list values) + { + return std::make_unique>(values); + } + + std::unique_ptr> makeEqualOrMaxSanitizerFloat(float equal, float max) + { + return std::make_unique>(equal, max); + } +} diff --git a/components/settings/sanitizerimpl.hpp b/components/settings/sanitizerimpl.hpp new file mode 100644 index 0000000000..b8f8f76af4 --- /dev/null +++ b/components/settings/sanitizerimpl.hpp @@ -0,0 +1,42 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_SANITIZERIMPL_H +#define OPENMW_COMPONENTS_SETTINGS_SANITIZERIMPL_H + +#include "sanitizer.hpp" + +#include + +#include +#include +#include +#include + +namespace Settings +{ + std::unique_ptr> makeMaxSanitizerFloat(float max); + + std::unique_ptr> makeMaxSanitizerInt(int max); + + std::unique_ptr> makeMaxSanitizerSize(std::size_t max); + + std::unique_ptr> makeMaxSanitizerUInt64(std::uint64_t max); + + std::unique_ptr> makeMaxStrictSanitizerFloat(float max); + + std::unique_ptr> makeMaxStrictSanitizerVec3f(const osg::Vec3f& max); + + std::unique_ptr> makeClampSanitizerFloat(float min, float max); + + std::unique_ptr> makeClampSanitizerDouble(double min, double max); + + std::unique_ptr> makeClampSanitizerInt(int min, int max); + + std::unique_ptr> makeClampStrictMaxSanitizerFloat(float min, float max); + + std::unique_ptr> makeEnumSanitizerInt(std::initializer_list values); + + std::unique_ptr> makeEnumSanitizerString(std::initializer_list values); + + std::unique_ptr> makeEqualOrMaxSanitizerFloat(float equal, float max); +} + +#endif diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index b389c63b6a..a99038cf08 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -1,5 +1,6 @@ #include "settings.hpp" #include "parser.hpp" +#include "values.hpp" #include #include @@ -79,11 +80,19 @@ namespace Settings return doubleValue; } #endif + template + std::string serialize(const T& value) + { + std::ostringstream stream; + stream << value; + return stream.str(); + } } CategorySettingValueMap Manager::mDefaultSettings = CategorySettingValueMap(); CategorySettingValueMap Manager::mUserSettings = CategorySettingValueMap(); CategorySettingVector Manager::mChangedSettings = CategorySettingVector(); + std::set> Manager::sInitialized; void Manager::clear() { @@ -136,6 +145,12 @@ namespace Settings if (std::filesystem::exists(settingspath)) parser.loadSettingsFile(settingspath, mUserSettings, false, false); + Settings::Values::init(); + + for (const auto& [key, value] : mDefaultSettings) + if (!sInitialized.contains(key)) + throw std::runtime_error("Default setting [" + key.first + "] " + key.second + " is not initialized"); + return settingspath; } @@ -203,6 +218,21 @@ namespace Settings return parseNumberFromSetting(getString(setting, category), setting, category); } + unsigned Manager::getUnsigned(std::string_view setting, std::string_view category) + { + return parseNumberFromSetting(getString(setting, category), setting, category); + } + + unsigned long Manager::getUnsignedLong(std::string_view setting, std::string_view category) + { + return parseNumberFromSetting(getString(setting, category), setting, category); + } + + unsigned long long Manager::getUnsignedLongLong(std::string_view setting, std::string_view category) + { + return parseNumberFromSetting(getString(setting, category), setting, category); + } + bool Manager::getBool(std::string_view setting, std::string_view category) { const std::string& string = getString(setting, category); @@ -360,4 +390,59 @@ namespace Settings } } + void Manager::set(std::string_view setting, std::string_view category, int value) + { + setInt(setting, category, value); + } + + void Manager::set(std::string_view setting, std::string_view category, unsigned value) + { + setString(setting, category, serialize(value)); + } + + void Manager::set(std::string_view setting, std::string_view category, unsigned long value) + { + setString(setting, category, serialize(value)); + } + + void Manager::set(std::string_view setting, std::string_view category, unsigned long long value) + { + setString(setting, category, serialize(value)); + } + + void Manager::set(std::string_view setting, std::string_view category, float value) + { + setFloat(setting, category, value); + } + + void Manager::set(std::string_view setting, std::string_view category, double value) + { + setDouble(setting, category, value); + } + + void Manager::set(std::string_view setting, std::string_view category, const std::string& value) + { + setString(setting, category, value); + } + + void Manager::set(std::string_view setting, std::string_view category, bool value) + { + setBool(setting, category, value); + } + + void Manager::set(std::string_view setting, std::string_view category, const osg::Vec2f& value) + { + setVector2(setting, category, value); + } + + void Manager::set(std::string_view setting, std::string_view category, const osg::Vec3f& value) + { + setVector3(setting, category, value); + } + + void Manager::recordInit(std::string_view setting, std::string_view category) + { + sInitialized.emplace(category, setting); + } + } diff --git a/components/settings/settings.hpp b/components/settings/settings.hpp index 5ca5aee461..5f3fb65aba 100644 --- a/components/settings/settings.hpp +++ b/components/settings/settings.hpp @@ -3,6 +3,7 @@ #include "categories.hpp" +#include #include #include #include @@ -61,6 +62,9 @@ namespace Settings static int getInt(std::string_view setting, std::string_view category); static std::uint64_t getUInt64(std::string_view setting, std::string_view category); static std::size_t getSize(std::string_view setting, std::string_view category); + static unsigned getUnsigned(std::string_view setting, std::string_view category); + static unsigned long getUnsignedLong(std::string_view setting, std::string_view category); + static unsigned long long getUnsignedLongLong(std::string_view setting, std::string_view category); static float getFloat(std::string_view setting, std::string_view category); static double getDouble(std::string_view setting, std::string_view category); static const std::string& getString(std::string_view setting, std::string_view category); @@ -69,6 +73,13 @@ namespace Settings static osg::Vec2f getVector2(std::string_view setting, std::string_view category); static osg::Vec3f getVector3(std::string_view setting, std::string_view category); + template + static T get(std::string_view setting, std::string_view category) + { + recordInit(setting, category); + return getImpl(setting, category); + } + static void setInt(std::string_view setting, std::string_view category, int value); static void setUInt64(std::string_view setting, std::string_view category, std::uint64_t value); static void setFloat(std::string_view setting, std::string_view category, float value); @@ -79,8 +90,86 @@ namespace Settings static void setBool(std::string_view setting, std::string_view category, bool value); static void setVector2(std::string_view setting, std::string_view category, osg::Vec2f value); static void setVector3(std::string_view setting, std::string_view category, osg::Vec3f value); + + static void set(std::string_view setting, std::string_view category, int value); + static void set(std::string_view setting, std::string_view category, unsigned value); + static void set(std::string_view setting, std::string_view category, unsigned long value); + static void set(std::string_view setting, std::string_view category, unsigned long long value); + static void set(std::string_view setting, std::string_view category, float value); + static void set(std::string_view setting, std::string_view category, double value); + static void set(std::string_view setting, std::string_view category, const std::string& value); + static void set(std::string_view setting, std::string_view category, bool value); + static void set(std::string_view setting, std::string_view category, const osg::Vec2f& value); + static void set(std::string_view setting, std::string_view category, const osg::Vec3f& value); + + private: + static std::set> sInitialized; + + template + static T getImpl(std::string_view setting, std::string_view category); + + static void recordInit(std::string_view setting, std::string_view category); }; + template <> + inline int Manager::getImpl(std::string_view setting, std::string_view category) + { + return getInt(setting, category); + } + + template <> + inline unsigned Manager::getImpl(std::string_view setting, std::string_view category) + { + return getUnsigned(setting, category); + } + + template <> + inline unsigned long Manager::getImpl(std::string_view setting, std::string_view category) + { + return getUnsignedLong(setting, category); + } + + template <> + inline unsigned long long Manager::getImpl(std::string_view setting, std::string_view category) + { + return getUnsignedLongLong(setting, category); + } + + template <> + inline float Manager::getImpl(std::string_view setting, std::string_view category) + { + return getFloat(setting, category); + } + + template <> + inline double Manager::getImpl(std::string_view setting, std::string_view category) + { + return getDouble(setting, category); + } + + template <> + inline std::string Manager::getImpl(std::string_view setting, std::string_view category) + { + return getString(setting, category); + } + + template <> + inline bool Manager::getImpl(std::string_view setting, std::string_view category) + { + return getBool(setting, category); + } + + template <> + inline osg::Vec2f Manager::getImpl(std::string_view setting, std::string_view category) + { + return getVector2(setting, category); + } + + template <> + inline osg::Vec3f Manager::getImpl(std::string_view setting, std::string_view category) + { + return getVector3(setting, category); + } } #endif // COMPONENTS_SETTINGS_H diff --git a/components/settings/settingvalue.hpp b/components/settings/settingvalue.hpp new file mode 100644 index 0000000000..e84f014c9b --- /dev/null +++ b/components/settings/settingvalue.hpp @@ -0,0 +1,70 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_SETTINGVALUE_H +#define OPENMW_COMPONENTS_SETTINGS_SETTINGVALUE_H + +#include "sanitizer.hpp" +#include "settings.hpp" + +#include "components/debug/debuglog.hpp" + +#include + +#include +#include +#include + +namespace Settings +{ + template + class SettingValue + { + public: + explicit SettingValue( + std::string_view category, std::string_view name, std::unique_ptr>&& sanitizer = nullptr) + : mCategory(category) + , mName(name) + , mSanitizer(std::move(sanitizer)) + , mValue(sanitize(Settings::Manager::get(name, category))) + { + } + + const T& get() const { return mValue; } + + operator const T&() const { return mValue; } + + void set(const T& value) + { + if (mValue == value) + return; + mValue = sanitize(value); + Settings::Manager::set(mName, mCategory, mValue); + } + + private: + const std::string_view mCategory; + const std::string_view mName; + const std::unique_ptr> mSanitizer; + T mValue{}; + + T sanitize(const T& value) const + { + if (mSanitizer == nullptr) + return value; + try + { + T sanitizedValue = mSanitizer->apply(value); + if (sanitizedValue != value) + Log(Debug::Warning) << "Setting [" << mCategory << "] " << mName + << " value is out of allowed values set: " << value << ", sanitized to " + << sanitizedValue; + return sanitizedValue; + } + catch (const std::exception& e) + { + throw std::runtime_error("Invalid setting [" + std::string(mCategory) + "] " + std::string(mName) + + " value: " + std::string(e.what())); + } + } + }; +} + +#endif diff --git a/components/settings/values.cpp b/components/settings/values.cpp new file mode 100644 index 0000000000..668a85c8fd --- /dev/null +++ b/components/settings/values.cpp @@ -0,0 +1,12 @@ +#include "values.hpp" + +namespace Settings +{ + Values* Values::sValues = nullptr; + + void Values::init() + { + static Values values; + Values::sValues = &values; + } +} diff --git a/components/settings/values.hpp b/components/settings/values.hpp new file mode 100644 index 0000000000..c6badbaa7c --- /dev/null +++ b/components/settings/values.hpp @@ -0,0 +1,201 @@ +#ifndef OPENMW_COMPONENTS_SETTINGS_VALUES_H +#define OPENMW_COMPONENTS_SETTINGS_VALUES_H + +#include "categories/camera.hpp" +#include "categories/cells.hpp" +#include "categories/fog.hpp" +#include "categories/game.hpp" +#include "categories/general.hpp" +#include "categories/groundcover.hpp" +#include "categories/gui.hpp" +#include "categories/hud.hpp" +#include "categories/input.hpp" +#include "categories/lua.hpp" +#include "categories/map.hpp" +#include "categories/models.hpp" +#include "categories/navigator.hpp" +#include "categories/physics.hpp" +#include "categories/postprocessing.hpp" +#include "categories/saves.hpp" +#include "categories/shaders.hpp" +#include "categories/shadows.hpp" +#include "categories/sound.hpp" +#include "categories/stereo.hpp" +#include "categories/stereoview.hpp" +#include "categories/terrain.hpp" +#include "categories/video.hpp" +#include "categories/water.hpp" +#include "categories/windows.hpp" + +namespace Settings +{ + class Values + { + 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 init(); + + private: + static Values* sValues; + + friend Values& values(); + }; + + inline Values& values() + { + return *Values::sValues; + } + + inline CameraCategory& camera() + { + return values().mCamera; + } + + inline CellsCategory& cells() + { + return values().mCells; + } + + inline TerrainCategory& terrain() + { + return values().mTerrain; + } + + inline FogCategory& fog() + { + return values().mFog; + } + + inline MapCategory& map() + { + return values().mMap; + } + + inline GUICategory& gui() + { + return values().mGUI; + } + + inline HUDCategory& hud() + { + return values().mHUD; + } + + inline GameCategory& game() + { + return values().mGame; + } + + inline GeneralCategory& general() + { + return values().mGeneral; + } + + inline ShadersCategory& shaders() + { + return values().mShaders; + } + + inline InputCategory& input() + { + return values().mInput; + } + + inline SavesCategory& saves() + { + return values().mSaves; + } + + inline SoundCategory& sound() + { + return values().mSound; + } + + inline VideoCategory& video() + { + return values().mVideo; + } + + inline WaterCategory& water() + { + return values().mWater; + } + + inline WindowsCategory& windows() + { + return values().mWindows; + } + + inline NavigatorCategory& navigator() + { + return values().mNavigator; + } + + inline ShadowsCategory& shadows() + { + return values().mShadows; + } + + inline PhysicsCategory& physics() + { + return values().mPhysics; + } + + inline ModelsCategory& models() + { + return values().mModels; + } + + inline GroundcoverCategory& groundcover() + { + return values().mGroundcover; + } + + inline LuaCategory& lua() + { + return values().mLua; + } + + inline StereoCategory& stereo() + { + return values().mStereo; + } + + inline StereoViewCategory& stereoView() + { + return values().mStereoView; + } + + inline PostProcessingCategory& postProcessing() + { + return values().mPostProcessing; + } + +} + +#endif