mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-04 15:19:09 +00:00
VideoCommon: add graphics mod editor state
This commit is contained in:
parent
0512bd9a18
commit
dc40e46651
2 changed files with 411 additions and 0 deletions
245
Source/Core/VideoCommon/GraphicsModEditor/EditorState.cpp
Normal file
245
Source/Core/VideoCommon/GraphicsModEditor/EditorState.cpp
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
// Copyright 2023 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "VideoCommon/GraphicsModEditor/EditorState.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "Common/EnumUtils.h"
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
#include "Common/VariantUtil.h"
|
||||||
|
|
||||||
|
#include "VideoCommon/GraphicsModSystem/Config/GraphicsMod.h"
|
||||||
|
#include "VideoCommon/GraphicsModSystem/Constants.h"
|
||||||
|
#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionFactory.h"
|
||||||
|
|
||||||
|
namespace GraphicsModEditor
|
||||||
|
{
|
||||||
|
void WriteToGraphicsMod(const UserData& user_data, GraphicsModSystem::Config::GraphicsMod* config)
|
||||||
|
{
|
||||||
|
config->m_title = user_data.m_title;
|
||||||
|
config->m_author = user_data.m_author;
|
||||||
|
config->m_description = user_data.m_description;
|
||||||
|
|
||||||
|
config->m_assets = user_data.m_asset_library->GetAssets(user_data.m_current_mod_path);
|
||||||
|
config->m_tags = user_data.m_tags;
|
||||||
|
|
||||||
|
std::map<GraphicsModAction*, std::size_t> action_to_index;
|
||||||
|
for (const auto& action : user_data.m_actions)
|
||||||
|
{
|
||||||
|
GraphicsModSystem::Config::GraphicsModAction action_config;
|
||||||
|
action_config.m_factory_name = action->GetFactoryName();
|
||||||
|
|
||||||
|
picojson::object serialized_data;
|
||||||
|
action->SerializeToConfig(&serialized_data);
|
||||||
|
action_config.m_data = picojson::value{serialized_data};
|
||||||
|
|
||||||
|
config->m_actions.push_back(std::move(action_config));
|
||||||
|
action_to_index[action.get()] = config->m_actions.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [tag_name, actions] : user_data.m_tag_name_to_actions)
|
||||||
|
{
|
||||||
|
auto& action_indexes = config->m_tag_name_to_action_indexes[tag_name];
|
||||||
|
for (const auto& action : actions)
|
||||||
|
{
|
||||||
|
action_indexes.push_back(action_to_index[action]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<GraphicsModSystem::DrawCallID> draw_calls;
|
||||||
|
for (const auto& [draw_call_id, actions] : user_data.m_draw_call_id_to_actions)
|
||||||
|
{
|
||||||
|
draw_calls.insert(draw_call_id);
|
||||||
|
}
|
||||||
|
for (const auto& [draw_call_id, actions] : user_data.m_draw_call_id_to_user_data)
|
||||||
|
{
|
||||||
|
draw_calls.insert(draw_call_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& draw_call_id : draw_calls)
|
||||||
|
{
|
||||||
|
const auto target_index = config->m_targets.size();
|
||||||
|
GraphicsModSystem::Config::IntTarget i_target;
|
||||||
|
i_target.m_target_id = Common::ToUnderlying(draw_call_id);
|
||||||
|
|
||||||
|
if (const auto iter = user_data.m_draw_call_id_to_actions.find(draw_call_id);
|
||||||
|
iter != user_data.m_draw_call_id_to_actions.end())
|
||||||
|
{
|
||||||
|
auto& action_indexes = config->m_target_index_to_action_indexes[target_index];
|
||||||
|
for (const auto& action : iter->second)
|
||||||
|
{
|
||||||
|
action_indexes.push_back(action_to_index[action]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto iter = user_data.m_draw_call_id_to_user_data.find(draw_call_id);
|
||||||
|
iter != user_data.m_draw_call_id_to_user_data.end())
|
||||||
|
{
|
||||||
|
i_target.m_name = iter->second.m_friendly_name;
|
||||||
|
|
||||||
|
for (const auto& tag_name : iter->second.m_tag_names)
|
||||||
|
{
|
||||||
|
i_target.m_tag_names.push_back(tag_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config->m_targets.push_back(std::move(i_target));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<GraphicsModSystem::TextureCacheID> texture_cache_ids;
|
||||||
|
for (const auto& [texture_cache_id, actions] : user_data.m_texture_cache_id_to_actions)
|
||||||
|
{
|
||||||
|
texture_cache_ids.insert(texture_cache_id);
|
||||||
|
}
|
||||||
|
for (const auto& [texture_cache_id, actions] : user_data.m_texture_cache_id_to_user_data)
|
||||||
|
{
|
||||||
|
texture_cache_ids.insert(texture_cache_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& texture_cache_id : texture_cache_ids)
|
||||||
|
{
|
||||||
|
const auto target_index = config->m_targets.size();
|
||||||
|
GraphicsModSystem::Config::StringTarget s_target;
|
||||||
|
s_target.m_target_id = texture_cache_id;
|
||||||
|
|
||||||
|
if (const auto iter = user_data.m_texture_cache_id_to_actions.find(texture_cache_id);
|
||||||
|
iter != user_data.m_texture_cache_id_to_actions.end())
|
||||||
|
{
|
||||||
|
auto& action_indexes = config->m_target_index_to_action_indexes[target_index];
|
||||||
|
for (const auto& action : iter->second)
|
||||||
|
{
|
||||||
|
action_indexes.push_back(action_to_index[action]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto iter = user_data.m_texture_cache_id_to_user_data.find(texture_cache_id);
|
||||||
|
iter != user_data.m_texture_cache_id_to_user_data.end())
|
||||||
|
{
|
||||||
|
s_target.m_name = iter->second.m_friendly_name;
|
||||||
|
|
||||||
|
for (const auto& tag_name : iter->second.m_tag_names)
|
||||||
|
{
|
||||||
|
s_target.m_tag_names.push_back(tag_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config->m_targets.push_back(std::move(s_target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadFromGraphicsMod(UserData* user_data, EditorData* editor_data,
|
||||||
|
const RuntimeState& runtime_state,
|
||||||
|
const GraphicsModSystem::Config::GraphicsMod& config,
|
||||||
|
const std::string& mod_root)
|
||||||
|
{
|
||||||
|
user_data->m_title = config.m_title;
|
||||||
|
user_data->m_author = config.m_author;
|
||||||
|
user_data->m_description = config.m_description;
|
||||||
|
user_data->m_current_mod_path = mod_root;
|
||||||
|
|
||||||
|
user_data->m_asset_library->AddAssets(config.m_assets, user_data->m_current_mod_path);
|
||||||
|
|
||||||
|
const auto create_action =
|
||||||
|
[&](const std::string_view& action_name,
|
||||||
|
const picojson::value& json_data) -> std::unique_ptr<GraphicsModAction> {
|
||||||
|
auto action =
|
||||||
|
GraphicsModActionFactory::Create(action_name, json_data, user_data->m_asset_library);
|
||||||
|
if (action == nullptr)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return action;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& action_config : config.m_actions)
|
||||||
|
{
|
||||||
|
if (auto action = create_action(action_config.m_factory_name, action_config.m_data))
|
||||||
|
{
|
||||||
|
user_data->m_actions.push_back(std::make_unique<EditorAction>(std::move(action)));
|
||||||
|
user_data->m_actions.back().get()->SetID(editor_data->m_next_action_id);
|
||||||
|
editor_data->m_next_action_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
user_data->m_tags = config.m_tags;
|
||||||
|
|
||||||
|
for (const auto& target : config.m_targets)
|
||||||
|
{
|
||||||
|
std::visit(
|
||||||
|
overloaded{
|
||||||
|
[&](const GraphicsModSystem::Config::IntTarget& int_target) {
|
||||||
|
const GraphicsModSystem::DrawCallID draw_call_id{int_target.m_target_id};
|
||||||
|
auto& actions = user_data->m_draw_call_id_to_actions[draw_call_id];
|
||||||
|
actions = {};
|
||||||
|
|
||||||
|
if (int_target.m_name != "")
|
||||||
|
{
|
||||||
|
user_data->m_draw_call_id_to_user_data[draw_call_id].m_friendly_name =
|
||||||
|
int_target.m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& tag_name : int_target.m_tag_names)
|
||||||
|
{
|
||||||
|
user_data->m_draw_call_id_to_user_data[draw_call_id].m_tag_names.push_back(
|
||||||
|
tag_name);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[&](const GraphicsModSystem::Config::StringTarget& str_target) {
|
||||||
|
const GraphicsModSystem::TextureCacheID texture_cache_id{str_target.m_target_id};
|
||||||
|
auto& actions = user_data->m_texture_cache_id_to_actions[texture_cache_id];
|
||||||
|
actions = {};
|
||||||
|
|
||||||
|
if (str_target.m_name != "")
|
||||||
|
{
|
||||||
|
user_data->m_texture_cache_id_to_user_data[texture_cache_id].m_friendly_name =
|
||||||
|
str_target.m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& tag_name : str_target.m_tag_names)
|
||||||
|
{
|
||||||
|
user_data->m_texture_cache_id_to_user_data[texture_cache_id].m_tag_names.push_back(
|
||||||
|
tag_name);
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
target);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& target_to_actions_pair : config.m_target_index_to_action_indexes)
|
||||||
|
{
|
||||||
|
const u64 target_index = target_to_actions_pair.first;
|
||||||
|
const std::vector<u64>& action_indexes = target_to_actions_pair.second;
|
||||||
|
std::visit(
|
||||||
|
overloaded{[&](const GraphicsModSystem::Config::IntTarget& int_target) {
|
||||||
|
const GraphicsModSystem::DrawCallID draw_call_id{int_target.m_target_id};
|
||||||
|
auto& actions = user_data->m_draw_call_id_to_actions[draw_call_id];
|
||||||
|
|
||||||
|
for (const auto& action_index : action_indexes)
|
||||||
|
{
|
||||||
|
actions.push_back(user_data->m_actions[action_index].get());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[&](const GraphicsModSystem::Config::StringTarget& str_target) {
|
||||||
|
const GraphicsModSystem::TextureCacheID texture_cache_id{
|
||||||
|
str_target.m_target_id};
|
||||||
|
auto& actions = user_data->m_texture_cache_id_to_actions[texture_cache_id];
|
||||||
|
|
||||||
|
for (const auto& action_index : action_indexes)
|
||||||
|
{
|
||||||
|
actions.push_back(user_data->m_actions[action_index].get());
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
config.m_targets[target_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [tag_name, action_indexes] : config.m_tag_name_to_action_indexes)
|
||||||
|
{
|
||||||
|
auto& actions = user_data->m_tag_name_to_actions[tag_name];
|
||||||
|
for (const auto& action_index : action_indexes)
|
||||||
|
{
|
||||||
|
actions.push_back(user_data->m_actions[action_index].get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace GraphicsModEditor
|
166
Source/Core/VideoCommon/GraphicsModEditor/EditorState.h
Normal file
166
Source/Core/VideoCommon/GraphicsModEditor/EditorState.h
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
// Copyright 2023 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <picojson.h>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
#include "VideoCommon/AbstractTexture.h"
|
||||||
|
#include "VideoCommon/Assets/CustomAsset.h"
|
||||||
|
#include "VideoCommon/Assets/DirectFilesystemAssetLibrary.h"
|
||||||
|
#include "VideoCommon/GraphicsModEditor/EditorAssetSource.h"
|
||||||
|
#include "VideoCommon/GraphicsModEditor/EditorTypes.h"
|
||||||
|
#include "VideoCommon/GraphicsModEditor/SceneDumper.h"
|
||||||
|
#include "VideoCommon/GraphicsModSystem/Config/GraphicsModHashPolicy.h"
|
||||||
|
#include "VideoCommon/GraphicsModSystem/Config/GraphicsModTag.h"
|
||||||
|
#include "VideoCommon/GraphicsModSystem/Runtime/CustomTextureCache.h"
|
||||||
|
#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModAction.h"
|
||||||
|
#include "VideoCommon/GraphicsModSystem/Types.h"
|
||||||
|
|
||||||
|
namespace GraphicsModSystem::Config
|
||||||
|
{
|
||||||
|
struct GraphicsMod;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GraphicsModEditor
|
||||||
|
{
|
||||||
|
struct EditorData
|
||||||
|
{
|
||||||
|
// A map of editor specific textures accessible by name
|
||||||
|
std::map<std::string, std::unique_ptr<AbstractTexture>> m_name_to_texture;
|
||||||
|
|
||||||
|
// A map of editor specific templates accessible by name
|
||||||
|
std::map<std::string, std::string> m_name_to_template;
|
||||||
|
|
||||||
|
// Editor specific tags
|
||||||
|
std::map<std::string, GraphicsModSystem::Config::GraphicsModTag> m_tags;
|
||||||
|
|
||||||
|
// User data that is waiting on the editor to generate
|
||||||
|
// a preview
|
||||||
|
std::map<VideoCommon::CustomAssetLibrary::AssetID, std::shared_ptr<VideoCommon::CustomAsset>>
|
||||||
|
m_assets_waiting_for_preview;
|
||||||
|
|
||||||
|
std::shared_ptr<VideoCommon::DirectFilesystemAssetLibrary> m_asset_library;
|
||||||
|
|
||||||
|
bool m_disable_all_actions = false;
|
||||||
|
|
||||||
|
bool m_view_lighting = false;
|
||||||
|
bool m_view_normals = false;
|
||||||
|
|
||||||
|
GraphicsModSystem::DrawCallID m_export_dolphin_material_draw_call;
|
||||||
|
|
||||||
|
GraphicsModSystem::DrawCallID m_create_material_draw_call;
|
||||||
|
|
||||||
|
u64 m_next_action_id = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UserData
|
||||||
|
{
|
||||||
|
std::string m_title;
|
||||||
|
std::string m_author;
|
||||||
|
std::string m_description;
|
||||||
|
std::filesystem::path m_current_mod_path;
|
||||||
|
|
||||||
|
GraphicsModSystem::Config::HashPolicy m_hash_policy =
|
||||||
|
GraphicsModSystem::Config::GetDefaultHashPolicy();
|
||||||
|
|
||||||
|
// References of actions defined by the user to provide to the graphics mod interface
|
||||||
|
std::map<GraphicsModSystem::DrawCallID, std::vector<GraphicsModAction*>>
|
||||||
|
m_draw_call_id_to_actions;
|
||||||
|
|
||||||
|
// References of actions defined by the user to provide to the graphics mod interface
|
||||||
|
std::map<GraphicsModSystem::TextureCacheID, std::vector<GraphicsModAction*>>
|
||||||
|
m_texture_cache_id_to_actions;
|
||||||
|
|
||||||
|
// References of actions defined by the user to provide to the graphics mod interface
|
||||||
|
std::map<GraphicsModSystem::LightID, std::vector<GraphicsModAction*>>
|
||||||
|
m_light_id_to_reference_actions;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<EditorAction>> m_actions;
|
||||||
|
|
||||||
|
std::vector<GraphicsModSystem::Config::GraphicsModTag> m_tags;
|
||||||
|
|
||||||
|
// References of actions defined by the user to provide to the graphics mod interface
|
||||||
|
std::map<std::string, std::vector<GraphicsModAction*>> m_tag_name_to_actions;
|
||||||
|
|
||||||
|
// Mapping the draw call id to any user data for the target
|
||||||
|
std::map<GraphicsModSystem::DrawCallID, DrawCallUserData> m_draw_call_id_to_user_data;
|
||||||
|
|
||||||
|
// Mapping the texture cache id to any user data for the target
|
||||||
|
std::map<GraphicsModSystem::TextureCacheID, TextureCacheUserData> m_texture_cache_id_to_user_data;
|
||||||
|
|
||||||
|
// Mapping the light id to any user data for the target
|
||||||
|
std::map<GraphicsModSystem::LightID, LightUserData> m_light_id_to_user_data;
|
||||||
|
|
||||||
|
// The asset library provided to all user actions
|
||||||
|
std::shared_ptr<EditorAssetSource> m_asset_library;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RuntimeState
|
||||||
|
{
|
||||||
|
struct XFBData
|
||||||
|
{
|
||||||
|
struct DrawCallWithTime
|
||||||
|
{
|
||||||
|
GraphicsModSystem::DrawCallID draw_call_id;
|
||||||
|
std::chrono::steady_clock::time_point sort_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DrawCallWithTimeCompare
|
||||||
|
{
|
||||||
|
bool operator()(const DrawCallWithTime& lhs, const DrawCallWithTime& rhs) const
|
||||||
|
{
|
||||||
|
return lhs.sort_time < rhs.sort_time;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The draw call ids this frame
|
||||||
|
std::set<DrawCallWithTime, DrawCallWithTimeCompare> m_draw_call_ids;
|
||||||
|
|
||||||
|
// The EFB/XFB calls triggered this frame
|
||||||
|
std::set<GraphicsModSystem::TextureCacheID> m_texture_cache_ids;
|
||||||
|
|
||||||
|
// The game lights triggered this frame
|
||||||
|
std::set<GraphicsModSystem::LightID> m_light_ids;
|
||||||
|
};
|
||||||
|
std::map<std::string, XFBData, std::less<>> m_xfb_to_data;
|
||||||
|
std::vector<std::string> m_xfbs_presented;
|
||||||
|
|
||||||
|
XFBData m_current_xfb;
|
||||||
|
|
||||||
|
// Mapping the draw call id to the last known data
|
||||||
|
std::map<GraphicsModSystem::DrawCallID, DrawCallData> m_draw_call_id_to_data;
|
||||||
|
|
||||||
|
// Mapping the EFB/XFB calls to the last known data
|
||||||
|
std::map<GraphicsModSystem::TextureCacheID, TextureCacheData, std::less<>>
|
||||||
|
m_texture_cache_id_to_data;
|
||||||
|
|
||||||
|
// Mapping the game light id to the last known data
|
||||||
|
std::map<GraphicsModSystem::LightID, LightData> m_light_id_to_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EditorState
|
||||||
|
{
|
||||||
|
EditorData m_editor_data;
|
||||||
|
UserData m_user_data;
|
||||||
|
RuntimeState m_runtime_data;
|
||||||
|
SceneDumper m_scene_dumper;
|
||||||
|
};
|
||||||
|
|
||||||
|
void WriteToGraphicsMod(const UserData& user_data, GraphicsModSystem::Config::GraphicsMod* config);
|
||||||
|
void ReadFromGraphicsMod(UserData* user_data, EditorData* editor_data,
|
||||||
|
const RuntimeState& runtime_state,
|
||||||
|
const GraphicsModSystem::Config::GraphicsMod& config,
|
||||||
|
const std::string& mod_root);
|
||||||
|
|
||||||
|
} // namespace GraphicsModEditor
|
Loading…
Add table
Add a link
Reference in a new issue