From dc40e466513ceafb72ffe6965919242cf5056552 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Mon, 24 Jul 2023 00:41:37 -0500 Subject: [PATCH] VideoCommon: add graphics mod editor state --- .../GraphicsModEditor/EditorState.cpp | 245 ++++++++++++++++++ .../GraphicsModEditor/EditorState.h | 166 ++++++++++++ 2 files changed, 411 insertions(+) create mode 100644 Source/Core/VideoCommon/GraphicsModEditor/EditorState.cpp create mode 100644 Source/Core/VideoCommon/GraphicsModEditor/EditorState.h diff --git a/Source/Core/VideoCommon/GraphicsModEditor/EditorState.cpp b/Source/Core/VideoCommon/GraphicsModEditor/EditorState.cpp new file mode 100644 index 0000000000..25bb1c945e --- /dev/null +++ b/Source/Core/VideoCommon/GraphicsModEditor/EditorState.cpp @@ -0,0 +1,245 @@ +// Copyright 2023 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "VideoCommon/GraphicsModEditor/EditorState.h" + +#include + +#include + +#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 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 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 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 { + 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(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& 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 diff --git a/Source/Core/VideoCommon/GraphicsModEditor/EditorState.h b/Source/Core/VideoCommon/GraphicsModEditor/EditorState.h new file mode 100644 index 0000000000..705174e994 --- /dev/null +++ b/Source/Core/VideoCommon/GraphicsModEditor/EditorState.h @@ -0,0 +1,166 @@ +// Copyright 2023 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +#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> m_name_to_texture; + + // A map of editor specific templates accessible by name + std::map m_name_to_template; + + // Editor specific tags + std::map m_tags; + + // User data that is waiting on the editor to generate + // a preview + std::map> + m_assets_waiting_for_preview; + + std::shared_ptr 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> + m_draw_call_id_to_actions; + + // References of actions defined by the user to provide to the graphics mod interface + std::map> + m_texture_cache_id_to_actions; + + // References of actions defined by the user to provide to the graphics mod interface + std::map> + m_light_id_to_reference_actions; + + std::vector> m_actions; + + std::vector m_tags; + + // References of actions defined by the user to provide to the graphics mod interface + std::map> m_tag_name_to_actions; + + // Mapping the draw call id to any user data for the target + std::map m_draw_call_id_to_user_data; + + // Mapping the texture cache id to any user data for the target + std::map m_texture_cache_id_to_user_data; + + // Mapping the light id to any user data for the target + std::map m_light_id_to_user_data; + + // The asset library provided to all user actions + std::shared_ptr 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 m_draw_call_ids; + + // The EFB/XFB calls triggered this frame + std::set m_texture_cache_ids; + + // The game lights triggered this frame + std::set m_light_ids; + }; + std::map> m_xfb_to_data; + std::vector m_xfbs_presented; + + XFBData m_current_xfb; + + // Mapping the draw call id to the last known data + std::map m_draw_call_id_to_data; + + // Mapping the EFB/XFB calls to the last known data + std::map> + m_texture_cache_id_to_data; + + // Mapping the game light id to the last known data + std::map 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