From 6ee173023c68711a4f78d02db1fa25d35de89cdc Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Mon, 14 Oct 2024 17:39:00 -0700 Subject: [PATCH] fix: bug for loading features due to missing keys --- src/State.cpp | 212 +++++++++++++++++++++++++++++--------------------- src/State.h | 2 +- 2 files changed, 124 insertions(+), 90 deletions(-) diff --git a/src/State.cpp b/src/State.cpp index 0ed132a10..91ab5cf42 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -19,6 +19,19 @@ #include "Streamline.h" #include "Upscaling.h" +#define JSON_LOAD(setting_name, condition, json_data, action) \ + try { \ + if (condition) { \ + action; \ + } \ + } catch (const json::exception& e) { \ + logger::warn("JSON Error processing '{}': {}. JSON section: {}", \ + setting_name, e.what(), json_data.dump()); \ + throw(e); \ + } catch (const std::exception& e) { \ + logger::warn("General error processing '{}': {}", setting_name, e.what()); \ + } + void State::Draw() { const auto& shaderCache = SIE::ShaderCache::Instance(); @@ -130,7 +143,7 @@ static const std::string& GetConfigPath(State::ConfigMode a_configMode) } } -void State::Load(ConfigMode a_configMode) +void State::Load(ConfigMode a_configMode, bool a_allowReload) { ConfigMode configMode = a_configMode; auto& shaderCache = SIE::ShaderCache::Instance(); @@ -139,6 +152,7 @@ void State::Load(ConfigMode a_configMode) // Attempt to load the config file auto tryLoadConfig = [&](const std::string& path) { std::ifstream i(path); + logger::info("Attempting to open config file: {}", path); if (!i.is_open()) { logger::warn("Unable to open config file: {}", path); return false; @@ -174,109 +188,129 @@ void State::Load(ConfigMode a_configMode) } // Proceed with loading settings from the loaded configuration - if (settings["Menu"].is_object()) { - Menu::GetSingleton()->Load(settings["Menu"]); - } - if (settings["Advanced"].is_object()) { - json& advanced = settings["Advanced"]; - if (advanced["Dump Shaders"].is_boolean()) - shaderCache.SetDump(advanced["Dump Shaders"]); - if (advanced["Log Level"].is_number_integer()) - logLevel = static_cast((int)advanced["Log Level"]); - if (advanced["Shader Defines"].is_string()) - SetDefines(advanced["Shader Defines"]); - if (advanced["Compiler Threads"].is_number_integer()) - shaderCache.compilationThreadCount = std::clamp(advanced["Compiler Threads"].get(), 1, static_cast(std::thread::hardware_concurrency())); - if (advanced["Background Compiler Threads"].is_number_integer()) - shaderCache.backgroundCompilationThreadCount = std::clamp(advanced["Background Compiler Threads"].get(), 1, static_cast(std::thread::hardware_concurrency())); - if (advanced["Use FileWatcher"].is_boolean()) - shaderCache.SetFileWatcher(advanced["Use FileWatcher"]); - if (advanced["Extended Frame Annotations"].is_boolean()) - extendedFrameAnnotations = advanced["Extended Frame Annotations"]; - } + try { + // Load Menu settings + + JSON_LOAD("Menu", settings["Menu"].is_object(), settings["Menu"], logger::info("Loading Menu settings"); Menu::GetSingleton()->Load(settings["Menu"])); + + // Load Advanced settings + if (settings["Advanced"].is_object()) { + json& advanced = settings["Advanced"]; + logger::info("Loading Advanced settings"); + JSON_LOAD("Dump Shaders", advanced["Dump Shaders"].is_boolean(), advanced["Dump Shaders"], shaderCache.SetDump(advanced["Dump Shaders"])); + JSON_LOAD("Log Level", advanced["Log Level"].is_number_integer(), advanced["Log Level"], logLevel = static_cast((int)advanced["Log Level"])); + JSON_LOAD("Shader Defines", advanced["Shader Defines"].is_string(), advanced["Shader Defines"], SetDefines(advanced["Shader Defines"])); + JSON_LOAD("Compiler Threads", advanced["Compiler Threads"].is_number_integer(), advanced["Compiler Threads"], + shaderCache.compilationThreadCount = std::clamp(advanced["Compiler Threads"].get(), 1, static_cast(std::thread::hardware_concurrency()))); + JSON_LOAD("Background Compiler Threads", advanced["Background Compiler Threads"].is_number_integer(), advanced["Background Compiler Threads"], + shaderCache.backgroundCompilationThreadCount = std::clamp(advanced["Background Compiler Threads"].get(), 1, static_cast(std::thread::hardware_concurrency()))); + JSON_LOAD("Use FileWatcher", advanced["Use FileWatcher"].is_boolean(), advanced["Use FileWatcher"], shaderCache.SetFileWatcher(advanced["Use FileWatcher"])); + JSON_LOAD("Extended Frame Annotations", advanced["Extended Frame Annotations"].is_boolean(), advanced["Extended Frame Annotations"], extendedFrameAnnotations = advanced["Extended Frame Annotations"]); + } - if (settings["General"].is_object()) { - json& general = settings["General"]; + // Load General settings + if (settings["General"].is_object()) { + json& general = settings["General"]; + logger::info("Loading General settings"); + JSON_LOAD("Enable Shaders", general["Enable Shaders"].is_boolean(), general["Enable Shaders"], shaderCache.SetEnabled(general["Enable Shaders"])); + JSON_LOAD("Enable Disk Cache", general["Enable Disk Cache"].is_boolean(), general["Enable Disk Cache"], shaderCache.SetDiskCache(general["Enable Disk Cache"])); + JSON_LOAD("Enable Async", general["Enable Async"].is_boolean(), general["Enable Async"], shaderCache.SetAsync(general["Enable Async"])); + } - if (general["Enable Shaders"].is_boolean()) - shaderCache.SetEnabled(general["Enable Shaders"]); + // Load Replace Original Shaders settings + if (settings["Replace Original Shaders"].is_object()) { + json& originalShaders = settings["Replace Original Shaders"]; + logger::info("Loading Replace Original Shaders settings"); + for (int classIndex = 0; classIndex < RE::BSShader::Type::Total - 1; ++classIndex) { + auto name = magic_enum::enum_name((RE::BSShader::Type)(classIndex + 1)); + JSON_LOAD(name, originalShaders[name].is_boolean(), originalShaders[name], enabledClasses[classIndex] = originalShaders[name]); + } + } - if (general["Enable Disk Cache"].is_boolean()) - shaderCache.SetDiskCache(general["Enable Disk Cache"]); + // Ensure 'Disable at Boot' section exists in the JSON + if (!settings.contains("Disable at Boot") || !settings["Disable at Boot"].is_object()) { + settings["Disable at Boot"] = json::object(); // Initialize to an empty object if it doesn't exist + } - if (general["Enable Async"].is_boolean()) - shaderCache.SetAsync(general["Enable Async"]); - } + json& disabledFeaturesJson = settings["Disable at Boot"]; + logger::info("Loading 'Disable at Boot' settings"); - if (settings["Replace Original Shaders"].is_object()) { - json& originalShaders = settings["Replace Original Shaders"]; - for (int classIndex = 0; classIndex < RE::BSShader::Type::Total - 1; ++classIndex) { - auto name = magic_enum::enum_name((RE::BSShader::Type)(classIndex + 1)); - if (originalShaders[name].is_boolean()) { - enabledClasses[classIndex] = originalShaders[name]; - } else { - logger::warn("Invalid entry for shader class '{}', using default", name); - } + for (auto& [featureName, featureStatus] : disabledFeaturesJson.items()) { + JSON_LOAD(featureName, featureStatus.is_boolean(), featureStatus, disabledFeatures[featureName] = featureStatus.get()); } - } - // Ensure 'Disable at Boot' section exists in the JSON - if (!settings.contains("Disable at Boot") || !settings["Disable at Boot"].is_object()) { - // Initialize to an empty object if it doesn't exist - settings["Disable at Boot"] = json::object(); - } - json& disabledFeaturesJson = settings["Disable at Boot"]; + for (const auto& [featureName, _] : specialFeatures) { + if (IsFeatureDisabled(featureName)) { + logger::info("Special Feature '{}' disabled at boot", featureName); + } + } - for (auto& [featureName, featureStatus] : disabledFeaturesJson.items()) { - if (featureStatus.is_boolean()) { - disabledFeatures[featureName] = featureStatus.get(); + // Load TruePBR settings + auto truePBR = TruePBR::GetSingleton(); + auto& pbrJson = settings[truePBR->GetShortName()]; + if (pbrJson.is_object()) { + try { + logger::info("Loading TruePBR settings"); + truePBR->LoadSettings(pbrJson); + } catch (const json::exception& e) { + logger::warn("JSON error loading TruePBR settings: {}. JSON section: {}", e.what(), pbrJson.dump()); + } catch (const std::exception& e) { + logger::warn("General error loading TruePBR settings: {}", e.what()); + } } else { - logger::warn("Invalid entry for feature '{}' in 'Disable at Boot', expected boolean.", featureName); - } - } - for (const auto& [featureName, _] : specialFeatures) { - if (IsFeatureDisabled(featureName)) { - logger::info("Special Feature '{}' disabled at boot", featureName); + logger::warn("Missing settings for TruePBR, using default."); } - } - - auto truePBR = TruePBR::GetSingleton(); - auto& pbrJson = settings[truePBR->GetShortName()]; - if (pbrJson.is_object()) { - truePBR->LoadSettings(pbrJson); - } else { - logger::warn("Missing settings for TruePBR, using default."); - } - auto upscaling = Upscaling::GetSingleton(); - auto& upscalingJson = settings[upscaling->GetShortName()]; - if (upscalingJson.is_object()) { - upscaling->LoadSettings(upscalingJson); - } else { - logger::warn("Missing settings for Upscaling, using default."); - } + // Load Upscaling settings + auto upscaling = Upscaling::GetSingleton(); + auto& upscalingJson = settings[upscaling->GetShortName()]; + if (upscalingJson.is_object()) { + try { + logger::info("Loading Upscaling settings"); + upscaling->LoadSettings(upscalingJson); + } catch (const json::exception& e) { + logger::warn("JSON error loading Upscaling settings: {}. JSON section: {}", e.what(), upscalingJson.dump()); + } catch (const std::exception& e) { + logger::warn("General error loading Upscaling settings: {}", e.what()); + } + } else { + logger::warn("Missing settings for Upscaling, using default."); + } - for (auto* feature : Feature::GetFeatureList()) { - try { - const std::string featureName = feature->GetShortName(); - bool isDisabled = disabledFeatures.contains(featureName) && disabledFeatures[featureName]; - if (!isDisabled) { - feature->Load(settings); - } else { - logger::info("Feature '{}' is disabled at boot.", featureName); + for (auto* feature : Feature::GetFeatureList()) { + try { + const std::string featureName = feature->GetShortName(); + bool isDisabled = disabledFeatures.contains(featureName) && disabledFeatures[featureName]; + if (!isDisabled) { + logger::info("Loading Feature: '{}'", featureName); + feature->Load(settings); + } else { + logger::info("Feature '{}' is disabled at boot.", featureName); + } + } catch (const std::exception& e) { + feature->failedLoadedMessage = std::format( + "{}{} failed to load. Check CommunityShaders.log", + feature->failedLoadedMessage.empty() ? "" : feature->failedLoadedMessage + "\n", + feature->GetName()); + logger::warn("Error loading setting for feature '{}': {}", feature->GetShortName(), e.what()); } - } catch (const std::exception& e) { - feature->failedLoadedMessage = std::format( - "{}{} failed to load. Check CommunityShaders.log", - feature->failedLoadedMessage.empty() ? "" : feature->failedLoadedMessage + "\n", - feature->GetName()); - logger::warn("Error loading setting for feature '{}': {}", feature->GetShortName(), e.what()); } - } - if (settings["Version"].is_string() && settings["Version"].get() != Plugin::VERSION.string()) { - logger::info("Found older config for version {}; upgrading to {}", (std::string)settings["Version"], Plugin::VERSION.string()); - Save(configMode); + if (settings["Version"].is_string() && settings["Version"].get() != Plugin::VERSION.string()) { + logger::info("Found older config for version {}; upgrading to {}", (std::string)settings["Version"], Plugin::VERSION.string()); + Save(configMode); + } + logger::info("Loading Settings Complete"); + } catch (const json::exception& e) { + logger::info("General JSON error accessing settings: {}; recreating config", e.what()); + Save(a_configMode); + if (a_allowReload) + Load(a_configMode, false); + } catch (const std::exception& e) { + logger::info("General error accessing settings: {}; recreating config", e.what()); + Save(a_configMode); + if (a_allowReload) + Load(a_configMode, false); } } diff --git a/src/State.h b/src/State.h index eb9155689..e4454f84d 100644 --- a/src/State.h +++ b/src/State.h @@ -52,7 +52,7 @@ class State void Reset(); void Setup(); - void Load(ConfigMode a_configMode = ConfigMode::USER); + void Load(ConfigMode a_configMode = ConfigMode::USER, bool a_allowReload = true); void Save(ConfigMode a_configMode = ConfigMode::USER); void PostPostLoad();