dolphin/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.cpp

192 lines
5.4 KiB
C++

// Copyright 2022 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.h"
#include <map>
#include <sstream>
#include <string>
#include "Common/CommonPaths.h"
#include "Common/FileSearch.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Core/ConfigManager.h"
#include "VideoCommon/GraphicsModSystem/Config/GraphicsMod.h"
#include "VideoCommon/GraphicsModSystem/Constants.h"
#include "VideoCommon/HiresTextures.h"
GraphicsModGroupConfig::GraphicsModGroupConfig(const std::string& game_id) : m_game_id(game_id)
{
}
GraphicsModGroupConfig::~GraphicsModGroupConfig() = default;
GraphicsModGroupConfig::GraphicsModGroupConfig(const GraphicsModGroupConfig&) = default;
GraphicsModGroupConfig::GraphicsModGroupConfig(GraphicsModGroupConfig&&) = default;
GraphicsModGroupConfig& GraphicsModGroupConfig::operator=(const GraphicsModGroupConfig&) = default;
GraphicsModGroupConfig& GraphicsModGroupConfig::operator=(GraphicsModGroupConfig&&) = default;
void GraphicsModGroupConfig::Load()
{
const std::string file_path = GetPath();
std::set<std::string> known_paths;
if (File::Exists(file_path))
{
std::string json_data;
if (!File::ReadFileToString(file_path, json_data))
{
ERROR_LOG_FMT(VIDEO, "Failed to load graphics mod group json file '{}'", file_path);
return;
}
picojson::value root;
const auto error = picojson::parse(root, json_data);
if (!error.empty())
{
ERROR_LOG_FMT(VIDEO,
"Failed to load graphics mod group json file '{}' due to parse error: {}",
file_path, error);
return;
}
if (!root.is<picojson::object>())
{
ERROR_LOG_FMT(
VIDEO,
"Failed to load graphics mod group json file '{}' due to root not being an object!",
file_path);
return;
}
const auto& mods = root.get("mods");
if (mods.is<picojson::array>())
{
for (const auto& mod_json : mods.get<picojson::array>())
{
if (mod_json.is<picojson::object>())
{
const auto& mod_json_obj = mod_json.get<picojson::object>();
auto graphics_mod = GraphicsModConfig::Create(&mod_json_obj);
if (!graphics_mod)
{
continue;
}
graphics_mod->DeserializeFromProfile(mod_json_obj);
auto mod_full_path = graphics_mod->GetAbsolutePath();
known_paths.insert(std::move(mod_full_path));
m_graphics_mods.push_back(*graphics_mod);
}
}
}
}
const auto try_add_mod = [&known_paths, this](const std::string& dir,
GraphicsModConfig::Source source) {
auto file = dir + DIR_SEP + "metadata.json";
UnifyPathSeparators(file);
if (known_paths.find(file) != known_paths.end())
{
return;
}
const auto mod = GraphicsModConfig::Create(file, source);
if (mod)
{
m_graphics_mods.push_back(*mod);
}
};
const std::set<std::string> graphics_mod_user_directories =
GetTextureDirectoriesWithGameId(File::GetUserPath(D_GRAPHICSMOD_IDX), m_game_id);
for (const auto& graphics_mod_directory : graphics_mod_user_directories)
{
try_add_mod(graphics_mod_directory, GraphicsModConfig::Source::User);
}
const std::set<std::string> graphics_mod_system_directories = GetTextureDirectoriesWithGameId(
File::GetSysDirectory() + DOLPHIN_SYSTEM_GRAPHICS_MOD_DIR, m_game_id);
for (const auto& graphics_mod_directory : graphics_mod_system_directories)
{
try_add_mod(graphics_mod_directory, GraphicsModConfig::Source::System);
}
std::sort(m_graphics_mods.begin(), m_graphics_mods.end());
for (auto& mod : m_graphics_mods)
{
m_path_to_graphics_mod[mod.GetAbsolutePath()] = &mod;
}
m_change_count++;
}
void GraphicsModGroupConfig::Save() const
{
const std::string file_path = GetPath();
std::ofstream json_stream;
File::OpenFStream(json_stream, file_path, std::ios_base::out);
if (!json_stream.is_open())
{
ERROR_LOG_FMT(VIDEO, "Failed to open graphics mod group json file '{}' for writing", file_path);
return;
}
picojson::object serialized_root;
picojson::array serialized_mods;
for (const auto& mod : m_graphics_mods)
{
picojson::object serialized_mod;
mod.SerializeToProfile(&serialized_mod);
serialized_mods.push_back(picojson::value{serialized_mod});
}
serialized_root["mods"] = picojson::value{serialized_mods};
const auto output = picojson::value{serialized_root}.serialize(true);
json_stream << output;
}
void GraphicsModGroupConfig::SetChangeCount(u32 change_count)
{
m_change_count = change_count;
}
u32 GraphicsModGroupConfig::GetChangeCount() const
{
return m_change_count;
}
const std::vector<GraphicsModConfig>& GraphicsModGroupConfig::GetMods() const
{
return m_graphics_mods;
}
GraphicsModConfig* GraphicsModGroupConfig::GetMod(const std::string& absolute_path) const
{
if (const auto iter = m_path_to_graphics_mod.find(absolute_path);
iter != m_path_to_graphics_mod.end())
{
return iter->second;
}
return nullptr;
}
const std::string& GraphicsModGroupConfig::GetGameID() const
{
return m_game_id;
}
std::string GraphicsModGroupConfig::GetPath() const
{
const std::string game_mod_root = File::GetUserPath(D_CONFIG_IDX) + GRAPHICSMOD_CONFIG_DIR;
return fmt::format("{}/{}.json", game_mod_root, m_game_id);
}