diff options
| author | iwubcode <iwubcode@users.noreply.github.com> | 2022-02-26 00:19:38 -0600 |
|---|---|---|
| committer | iwubcode <iwubcode@users.noreply.github.com> | 2022-06-27 18:20:52 -0500 |
| commit | 254246b814124f0f1dff5e1aebd9672c0d1bd492 (patch) | |
| tree | aed28905acb212070b6ae93f65959aa11b0ef51f /Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp | |
| parent | f92beb611f5e7effc9d1b8a90fbd4004233945ff (diff) | |
VideoCommon: add logic to read a GraphicsMod from configuration
Diffstat (limited to 'Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp new file mode 100644 index 0000000000..c7dc5aab87 --- /dev/null +++ b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp @@ -0,0 +1,291 @@ +// Copyright 2022 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "VideoCommon/GraphicsModSystem/Config/GraphicsMod.h" + +#include <fmt/format.h> + +#include "Common/CommonPaths.h" +#include "Common/FileUtil.h" +#include "Common/Logging/Log.h" +#include "Common/StringUtil.h" + +#include "VideoCommon/GraphicsModSystem/Constants.h" + +std::optional<GraphicsModConfig> GraphicsModConfig::Create(const std::string& file_path, + Source source) +{ + std::string json_data; + if (!File::ReadFileToString(file_path, json_data)) + { + ERROR_LOG_FMT(VIDEO, "Failed to load graphics mod json file '{}'", file_path); + return std::nullopt; + } + + picojson::value root; + const auto error = picojson::parse(root, json_data); + + if (!error.empty()) + { + ERROR_LOG_FMT(VIDEO, "Failed to load graphics mod json file '{}' due to parse error: {}", + file_path, error); + return std::nullopt; + } + + GraphicsModConfig result; + if (!result.DeserializeFromConfig(root)) + { + return std::nullopt; + } + result.m_source = source; + if (source == Source::User) + { + const std::string base_path = File::GetUserPath(D_GRAPHICSMOD_IDX); + if (base_path.size() > file_path.size()) + { + ERROR_LOG_FMT( + VIDEO, + "Failed to load graphics mod json file '{}' due to it not matching the base path: {}", + file_path, base_path); + return std::nullopt; + } + result.m_relative_path = file_path.substr(base_path.size()); + } + else + { + const std::string base_path = File::GetSysDirectory() + DOLPHIN_SYSTEM_GRAPHICS_MOD_DIR; + if (base_path.size() > file_path.size()) + { + ERROR_LOG_FMT( + VIDEO, + "Failed to load graphics mod json file '{}' due to it not matching the base path: {}", + file_path, base_path); + return std::nullopt; + } + result.m_relative_path = file_path.substr(base_path.size()); + } + + return result; +} + +std::optional<GraphicsModConfig> GraphicsModConfig::Create(const picojson::object* obj) +{ + if (!obj) + return std::nullopt; + + const auto source_it = obj->find("source"); + if (source_it == obj->end()) + { + return std::nullopt; + } + const std::string source_str = source_it->second.to_str(); + + const auto path_it = obj->find("path"); + if (path_it == obj->end()) + { + return std::nullopt; + } + const std::string relative_path = path_it->second.to_str(); + + if (source_str == "system") + { + return Create(fmt::format("{}{}{}", File::GetSysDirectory(), DOLPHIN_SYSTEM_GRAPHICS_MOD_DIR, + relative_path), + Source::System); + } + else + { + return Create(File::GetUserPath(D_GRAPHICSMOD_IDX) + relative_path, Source::User); + } +} + +std::string GraphicsModConfig::GetAbsolutePath() const +{ + if (m_source == Source::System) + { + return WithUnifiedPathSeparators(fmt::format("{}{}{}", File::GetSysDirectory(), + DOLPHIN_SYSTEM_GRAPHICS_MOD_DIR, m_relative_path)); + } + else + { + return WithUnifiedPathSeparators(File::GetUserPath(D_GRAPHICSMOD_IDX) + m_relative_path); + } +} + +bool GraphicsModConfig::DeserializeFromConfig(const picojson::value& value) +{ + const auto& meta = value.get("meta"); + if (meta.is<picojson::object>()) + { + const auto& title = meta.get("title"); + if (title.is<std::string>()) + { + m_title = title.to_str(); + } + + const auto& author = meta.get("author"); + if (author.is<std::string>()) + { + m_author = author.to_str(); + } + + const auto& description = meta.get("description"); + if (description.is<std::string>()) + { + m_description = description.to_str(); + } + } + + const auto& groups = value.get("groups"); + if (groups.is<picojson::array>()) + { + for (const auto& group_val : groups.get<picojson::array>()) + { + if (!group_val.is<picojson::object>()) + { + ERROR_LOG_FMT( + VIDEO, "Failed to load mod configuration file, specified group is not a json object"); + return false; + } + GraphicsTargetGroupConfig group; + if (!group.DeserializeFromConfig(group_val.get<picojson::object>())) + { + return false; + } + + m_groups.push_back(group); + } + } + + const auto& features = value.get("features"); + if (features.is<picojson::array>()) + { + for (const auto& feature_val : features.get<picojson::array>()) + { + if (!feature_val.is<picojson::object>()) + { + ERROR_LOG_FMT( + VIDEO, "Failed to load mod configuration file, specified feature is not a json object"); + return false; + } + GraphicsModFeatureConfig feature; + if (!feature.DeserializeFromConfig(feature_val.get<picojson::object>())) + { + return false; + } + + m_features.push_back(feature); + } + } + + return true; +} + +void GraphicsModConfig::SerializeToProfile(picojson::object* obj) const +{ + if (!obj) + return; + + auto& json_obj = *obj; + switch (m_source) + { + case Source::User: + { + json_obj["source"] = picojson::value{"user"}; + } + break; + case Source::System: + { + json_obj["source"] = picojson::value{"system"}; + } + break; + }; + + json_obj["path"] = picojson::value{m_relative_path}; + + picojson::array serialized_groups; + for (const auto& group : m_groups) + { + picojson::object serialized_group; + group.SerializeToProfile(&serialized_group); + serialized_groups.push_back(picojson::value{serialized_group}); + } + json_obj["groups"] = picojson::value{serialized_groups}; + + picojson::array serialized_features; + for (const auto& feature : m_features) + { + picojson::object serialized_feature; + feature.SerializeToProfile(&serialized_feature); + serialized_features.push_back(picojson::value{serialized_feature}); + } + json_obj["features"] = picojson::value{serialized_features}; + + json_obj["enabled"] = picojson::value{m_enabled}; + + json_obj["weight"] = picojson::value{static_cast<double>(m_weight)}; +} + +void GraphicsModConfig::DeserializeFromProfile(const picojson::object& obj) +{ + if (const auto it = obj.find("groups"); it != obj.end()) + { + if (it->second.is<picojson::array>()) + { + auto serialized_groups = it->second.get<picojson::array>(); + if (serialized_groups.size() != m_groups.size()) + return; + + for (std::size_t i = 0; i < serialized_groups.size(); i++) + { + const auto& serialized_group_val = serialized_groups[i]; + if (serialized_group_val.is<picojson::object>()) + { + const auto& serialized_group = serialized_group_val.get<picojson::object>(); + m_groups[i].DeserializeFromProfile(serialized_group); + } + } + } + } + + if (const auto it = obj.find("features"); it != obj.end()) + { + if (it->second.is<picojson::array>()) + { + auto serialized_features = it->second.get<picojson::array>(); + if (serialized_features.size() != m_features.size()) + return; + + for (std::size_t i = 0; i < serialized_features.size(); i++) + { + const auto& serialized_feature_val = serialized_features[i]; + if (serialized_feature_val.is<picojson::object>()) + { + const auto& serialized_feature = serialized_feature_val.get<picojson::object>(); + m_features[i].DeserializeFromProfile(serialized_feature); + } + } + } + } + + if (const auto it = obj.find("enabled"); it != obj.end()) + { + if (it->second.is<bool>()) + { + m_enabled = it->second.get<bool>(); + } + } + + if (const auto it = obj.find("weight"); it != obj.end()) + { + if (it->second.is<double>()) + { + m_weight = static_cast<u16>(it->second.get<double>()); + } + } +} + +bool GraphicsModConfig::operator<(const GraphicsModConfig& other) const +{ + return m_weight < other.m_weight; +} |
