diff options
| author | 2021-07-23 12:41:07 -0400 | |
|---|---|---|
| committer | 2021-07-30 13:33:21 -0400 | |
| commit | a1f19b61f84f709ba20c350da34956c5455a6956 (patch) | |
| tree | 41fa169bc46040180fa165697b6477fd2dbe98ad | |
| parent | Merge pull request #6767 from ReinUsesLisp/fold-float-pack (diff) | |
| download | yuzu-a1f19b61f84f709ba20c350da34956c5455a6956.tar.gz yuzu-a1f19b61f84f709ba20c350da34956c5455a6956.tar.xz yuzu-a1f19b61f84f709ba20c350da34956c5455a6956.zip | |
settings: Implement setting ranges
Clamps the setting's values against the specified minimum and maximum
values.
Diffstat (limited to '')
| -rw-r--r-- | src/common/settings.h | 170 |
1 files changed, 152 insertions, 18 deletions
diff --git a/src/common/settings.h b/src/common/settings.h index cfc1ab46f..51f9a179b 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -142,6 +142,67 @@ protected: | |||
| 142 | }; | 142 | }; |
| 143 | 143 | ||
| 144 | /** | 144 | /** |
| 145 | * BasicRangedSetting class is intended for use with quantifiable settings that need a more | ||
| 146 | * restrictive range than implicitly defined by its type. Implements a minimum and maximum that is | ||
| 147 | * simply used to sanitize SetValue and the assignment overload. | ||
| 148 | */ | ||
| 149 | template <typename Type> | ||
| 150 | class BasicRangedSetting : virtual public BasicSetting<Type> { | ||
| 151 | public: | ||
| 152 | /** | ||
| 153 | * Sets a default value, minimum value, maximum value, and label. | ||
| 154 | * | ||
| 155 | * @param default_val Intial value of the setting, and default value of the setting | ||
| 156 | * @param min_val Sets the minimum allowed value of the setting | ||
| 157 | * @param max_val Sets the maximum allowed value of the setting | ||
| 158 | * @param name Label for the setting | ||
| 159 | */ | ||
| 160 | explicit BasicRangedSetting(const Type& default_val, const Type& min_val, const Type& max_val, | ||
| 161 | const std::string& name) | ||
| 162 | : BasicSetting<Type>{default_val, name}, minimum{min_val}, maximum{max_val} {} | ||
| 163 | ~BasicRangedSetting() = default; | ||
| 164 | |||
| 165 | /** | ||
| 166 | * Like BasicSetting's SetValue, except value is clamped to the range of the setting. | ||
| 167 | * | ||
| 168 | * @param value The desired value | ||
| 169 | */ | ||
| 170 | void SetValue(const Type& value) { | ||
| 171 | Type temp; | ||
| 172 | if (value < minimum) { | ||
| 173 | temp = std::move(minimum); | ||
| 174 | } else if (value > maximum) { | ||
| 175 | temp = std::move(maximum); | ||
| 176 | } else { | ||
| 177 | temp = std::move(value); | ||
| 178 | } | ||
| 179 | std::swap(this->global, temp); | ||
| 180 | } | ||
| 181 | |||
| 182 | /** | ||
| 183 | * Like BasicSetting's assignment overload, except value is clamped to the range of the setting. | ||
| 184 | * | ||
| 185 | * @param value The desired value | ||
| 186 | * @returns A reference to the setting's value | ||
| 187 | */ | ||
| 188 | const Type& operator=(const Type& value) { | ||
| 189 | Type temp; | ||
| 190 | if (value < minimum) { | ||
| 191 | temp = std::move(minimum); | ||
| 192 | } else if (value > maximum) { | ||
| 193 | temp = std::move(maximum); | ||
| 194 | } else { | ||
| 195 | temp = std::move(value); | ||
| 196 | } | ||
| 197 | std::swap(this->global, temp); | ||
| 198 | return this->global; | ||
| 199 | } | ||
| 200 | |||
| 201 | const Type minimum; ///< Minimum allowed value of the setting | ||
| 202 | const Type maximum; ///< Maximum allowed value of the setting | ||
| 203 | }; | ||
| 204 | |||
| 205 | /** | ||
| 145 | * The Setting class is a slightly more complex version of the BasicSetting class. This adds a | 206 | * The Setting class is a slightly more complex version of the BasicSetting class. This adds a |
| 146 | * custom setting to switch to when a guest application specifically requires it. The effect is that | 207 | * custom setting to switch to when a guest application specifically requires it. The effect is that |
| 147 | * other components of the emulator can access the setting's intended value without any need for the | 208 | * other components of the emulator can access the setting's intended value without any need for the |
| @@ -152,7 +213,7 @@ protected: | |||
| 152 | * Like the BasicSetting, this requires setting a default value and label to use. | 213 | * Like the BasicSetting, this requires setting a default value and label to use. |
| 153 | */ | 214 | */ |
| 154 | template <typename Type> | 215 | template <typename Type> |
| 155 | class Setting final : public BasicSetting<Type> { | 216 | class Setting : virtual public BasicSetting<Type> { |
| 156 | public: | 217 | public: |
| 157 | /** | 218 | /** |
| 158 | * Sets a default value, label, and setting value. | 219 | * Sets a default value, label, and setting value. |
| @@ -241,12 +302,81 @@ public: | |||
| 241 | return custom; | 302 | return custom; |
| 242 | } | 303 | } |
| 243 | 304 | ||
| 244 | private: | 305 | protected: |
| 245 | bool use_global{true}; ///< The setting's global state | 306 | bool use_global{true}; ///< The setting's global state |
| 246 | Type custom{}; ///< The custom value of the setting | 307 | Type custom{}; ///< The custom value of the setting |
| 247 | }; | 308 | }; |
| 248 | 309 | ||
| 249 | /** | 310 | /** |
| 311 | * RangedSetting is a Setting that implements a maximum and minimum value for its setting. Intended | ||
| 312 | * for use with quantifiable settings. | ||
| 313 | */ | ||
| 314 | template <typename Type> | ||
| 315 | class RangedSetting final : public BasicRangedSetting<Type>, public Setting<Type> { | ||
| 316 | public: | ||
| 317 | /** | ||
| 318 | * Sets a default value, minimum value, maximum value, and label. | ||
| 319 | * | ||
| 320 | * @param default_val Intial value of the setting, and default value of the setting | ||
| 321 | * @param min_val Sets the minimum allowed value of the setting | ||
| 322 | * @param max_val Sets the maximum allowed value of the setting | ||
| 323 | * @param name Label for the setting | ||
| 324 | */ | ||
| 325 | explicit RangedSetting(const Type& default_val, const Type& min_val, const Type& max_val, | ||
| 326 | const std::string& name) | ||
| 327 | : BasicSetting<Type>{default_val, name}, | ||
| 328 | BasicRangedSetting<Type>{default_val, min_val, max_val, name}, Setting<Type>{default_val, | ||
| 329 | name} {} | ||
| 330 | ~RangedSetting() = default; | ||
| 331 | |||
| 332 | /** | ||
| 333 | * Like BasicSetting's SetValue, except value is clamped to the range of the setting. Sets the | ||
| 334 | * appropriate value depending on the global state. | ||
| 335 | * | ||
| 336 | * @param value The desired value | ||
| 337 | */ | ||
| 338 | void SetValue(const Type& value) { | ||
| 339 | Type temp; | ||
| 340 | if (value < this->minimum) { | ||
| 341 | temp = std::move(this->minimum); | ||
| 342 | } else if (value > this->maximum) { | ||
| 343 | temp = std::move(this->maximum); | ||
| 344 | } else { | ||
| 345 | temp = std::move(value); | ||
| 346 | } | ||
| 347 | if (this->use_global) { | ||
| 348 | std::swap(this->global, temp); | ||
| 349 | } else { | ||
| 350 | std::swap(this->custom, temp); | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | /** | ||
| 355 | * Like BasicSetting's assignment overload, except value is clamped to the range of the setting. | ||
| 356 | * Uses the appropriate value depending on the global state. | ||
| 357 | * | ||
| 358 | * @param value The desired value | ||
| 359 | * @returns A reference to the setting's value | ||
| 360 | */ | ||
| 361 | const Type& operator=(const Type& value) { | ||
| 362 | Type temp; | ||
| 363 | if (value < this->minimum) { | ||
| 364 | temp = std::move(this->minimum); | ||
| 365 | } else if (value > this->maximum) { | ||
| 366 | temp = std::move(this->maximum); | ||
| 367 | } else { | ||
| 368 | temp = std::move(value); | ||
| 369 | } | ||
| 370 | if (this->use_global) { | ||
| 371 | std::swap(this->global, temp); | ||
| 372 | return this->global; | ||
| 373 | } | ||
| 374 | std::swap(this->custom, temp); | ||
| 375 | return this->custom; | ||
| 376 | } | ||
| 377 | }; | ||
| 378 | |||
| 379 | /** | ||
| 250 | * The InputSetting class allows for getting a reference to either the global or custom members. | 380 | * The InputSetting class allows for getting a reference to either the global or custom members. |
| 251 | * This is required as we cannot easily modify the values of user-defined types within containers | 381 | * This is required as we cannot easily modify the values of user-defined types within containers |
| 252 | * using the SetValue() member function found in the Setting class. The primary purpose of this | 382 | * using the SetValue() member function found in the Setting class. The primary purpose of this |
| @@ -289,13 +419,14 @@ struct Values { | |||
| 289 | BasicSetting<std::string> sink_id{"auto", "output_engine"}; | 419 | BasicSetting<std::string> sink_id{"auto", "output_engine"}; |
| 290 | BasicSetting<bool> audio_muted{false, "audio_muted"}; | 420 | BasicSetting<bool> audio_muted{false, "audio_muted"}; |
| 291 | Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; | 421 | Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; |
| 292 | Setting<u8> volume{100, "volume"}; | 422 | RangedSetting<u8> volume{100, 0, 100, "volume"}; |
| 293 | 423 | ||
| 294 | // Core | 424 | // Core |
| 295 | Setting<bool> use_multi_core{true, "use_multi_core"}; | 425 | Setting<bool> use_multi_core{true, "use_multi_core"}; |
| 296 | 426 | ||
| 297 | // Cpu | 427 | // Cpu |
| 298 | Setting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, "cpu_accuracy"}; | 428 | RangedSetting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, |
| 429 | CPUAccuracy::Unsafe, "cpu_accuracy"}; | ||
| 299 | // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021 | 430 | // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021 |
| 300 | BasicSetting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; | 431 | BasicSetting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; |
| 301 | BasicSetting<bool> cpu_debug_mode{false, "cpu_debug_mode"}; | 432 | BasicSetting<bool> cpu_debug_mode{false, "cpu_debug_mode"}; |
| @@ -317,7 +448,8 @@ struct Values { | |||
| 317 | Setting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"}; | 448 | Setting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"}; |
| 318 | 449 | ||
| 319 | // Renderer | 450 | // Renderer |
| 320 | Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"}; | 451 | RangedSetting<RendererBackend> renderer_backend{ |
| 452 | RendererBackend::OpenGL, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"}; | ||
| 321 | BasicSetting<bool> renderer_debug{false, "debug"}; | 453 | BasicSetting<bool> renderer_debug{false, "debug"}; |
| 322 | BasicSetting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; | 454 | BasicSetting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; |
| 323 | BasicSetting<bool> disable_shader_loop_safety_checks{false, | 455 | BasicSetting<bool> disable_shader_loop_safety_checks{false, |
| @@ -327,26 +459,28 @@ struct Values { | |||
| 327 | Setting<u16> resolution_factor{1, "resolution_factor"}; | 459 | Setting<u16> resolution_factor{1, "resolution_factor"}; |
| 328 | // *nix platforms may have issues with the borderless windowed fullscreen mode. | 460 | // *nix platforms may have issues with the borderless windowed fullscreen mode. |
| 329 | // Default to exclusive fullscreen on these platforms for now. | 461 | // Default to exclusive fullscreen on these platforms for now. |
| 330 | Setting<FullscreenMode> fullscreen_mode{ | 462 | RangedSetting<FullscreenMode> fullscreen_mode{ |
| 331 | #ifdef _WIN32 | 463 | #ifdef _WIN32 |
| 332 | FullscreenMode::Borderless, | 464 | FullscreenMode::Borderless, |
| 333 | #else | 465 | #else |
| 334 | FullscreenMode::Exclusive, | 466 | FullscreenMode::Exclusive, |
| 335 | #endif | 467 | #endif |
| 336 | "fullscreen_mode"}; | 468 | FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"}; |
| 337 | Setting<int> aspect_ratio{0, "aspect_ratio"}; | 469 | RangedSetting<int> aspect_ratio{0, 0, 3, "aspect_ratio"}; |
| 338 | Setting<int> max_anisotropy{0, "max_anisotropy"}; | 470 | RangedSetting<int> max_anisotropy{0, 0, 4, "max_anisotropy"}; |
| 339 | Setting<bool> use_speed_limit{true, "use_speed_limit"}; | 471 | Setting<bool> use_speed_limit{true, "use_speed_limit"}; |
| 340 | Setting<u16> speed_limit{100, "speed_limit"}; | 472 | RangedSetting<u16> speed_limit{100, 0, 9999, "speed_limit"}; |
| 341 | Setting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; | 473 | Setting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; |
| 342 | Setting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, "gpu_accuracy"}; | 474 | RangedSetting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal, |
| 475 | GPUAccuracy::Extreme, "gpu_accuracy"}; | ||
| 343 | Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; | 476 | Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; |
| 344 | Setting<bool> use_nvdec_emulation{true, "use_nvdec_emulation"}; | 477 | Setting<bool> use_nvdec_emulation{true, "use_nvdec_emulation"}; |
| 345 | Setting<bool> accelerate_astc{true, "accelerate_astc"}; | 478 | Setting<bool> accelerate_astc{true, "accelerate_astc"}; |
| 346 | Setting<bool> use_vsync{true, "use_vsync"}; | 479 | Setting<bool> use_vsync{true, "use_vsync"}; |
| 347 | BasicSetting<u16> fps_cap{1000, "fps_cap"}; | 480 | BasicRangedSetting<u16> fps_cap{1000, 1, 1000, "fps_cap"}; |
| 348 | BasicSetting<bool> disable_fps_limit{false, "disable_fps_limit"}; | 481 | BasicSetting<bool> disable_fps_limit{false, "disable_fps_limit"}; |
| 349 | Setting<ShaderBackend> shader_backend{ShaderBackend::GLASM, "shader_backend"}; | 482 | RangedSetting<ShaderBackend> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL, |
| 483 | ShaderBackend::SPIRV, "shader_backend"}; | ||
| 350 | Setting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; | 484 | Setting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; |
| 351 | Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; | 485 | Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; |
| 352 | Setting<bool> use_caches_gc{false, "use_caches_gc"}; | 486 | Setting<bool> use_caches_gc{false, "use_caches_gc"}; |
| @@ -363,10 +497,10 @@ struct Values { | |||
| 363 | std::chrono::seconds custom_rtc_differential; | 497 | std::chrono::seconds custom_rtc_differential; |
| 364 | 498 | ||
| 365 | BasicSetting<s32> current_user{0, "current_user"}; | 499 | BasicSetting<s32> current_user{0, "current_user"}; |
| 366 | Setting<s32> language_index{1, "language_index"}; | 500 | RangedSetting<s32> language_index{1, 0, 16, "language_index"}; |
| 367 | Setting<s32> region_index{1, "region_index"}; | 501 | RangedSetting<s32> region_index{1, 0, 6, "region_index"}; |
| 368 | Setting<s32> time_zone_index{0, "time_zone_index"}; | 502 | RangedSetting<s32> time_zone_index{0, 0, 45, "time_zone_index"}; |
| 369 | Setting<s32> sound_index{1, "sound_index"}; | 503 | RangedSetting<s32> sound_index{1, 0, 2, "sound_index"}; |
| 370 | 504 | ||
| 371 | // Controls | 505 | // Controls |
| 372 | InputSetting<std::array<PlayerInput, 10>> players; | 506 | InputSetting<std::array<PlayerInput, 10>> players; |
| @@ -383,7 +517,7 @@ struct Values { | |||
| 383 | "udp_input_servers"}; | 517 | "udp_input_servers"}; |
| 384 | 518 | ||
| 385 | BasicSetting<bool> mouse_panning{false, "mouse_panning"}; | 519 | BasicSetting<bool> mouse_panning{false, "mouse_panning"}; |
| 386 | BasicSetting<u8> mouse_panning_sensitivity{10, "mouse_panning_sensitivity"}; | 520 | BasicRangedSetting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"}; |
| 387 | BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; | 521 | BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; |
| 388 | std::string mouse_device; | 522 | std::string mouse_device; |
| 389 | MouseButtonsRaw mouse_buttons; | 523 | MouseButtonsRaw mouse_buttons; |