diff options
| author | iwubcode <iwubcode@users.noreply.github.com> | 2023-07-02 21:27:24 -0500 |
|---|---|---|
| committer | iwubcode <iwubcode@users.noreply.github.com> | 2023-07-09 12:21:34 -0500 |
| commit | 77511e8e7cc80cc82fa1edf206948f714413aac8 (patch) | |
| tree | 112ec9a7f52b18023c9178035ea2e27a2653c053 /Source/Core/VideoCommon/Assets/MaterialAsset.cpp | |
| parent | 7bb04ff1dc7c528c794694edcc9802667345a6e3 (diff) | |
VideoCommon: add material asset. A material is similar to other graphics engines where it provides data to be used in conjunction with a shader asset to generate a runtime AbstractShader
Diffstat (limited to 'Source/Core/VideoCommon/Assets/MaterialAsset.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/Assets/MaterialAsset.cpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/Assets/MaterialAsset.cpp b/Source/Core/VideoCommon/Assets/MaterialAsset.cpp new file mode 100644 index 0000000000..c5e5718492 --- /dev/null +++ b/Source/Core/VideoCommon/Assets/MaterialAsset.cpp @@ -0,0 +1,166 @@ +// Copyright 2023 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "VideoCommon/Assets/MaterialAsset.h" + +#include <vector> + +#include "Common/Logging/Log.h" +#include "Common/StringUtil.h" +#include "VideoCommon/Assets/CustomAssetLibrary.h" + +namespace VideoCommon +{ +namespace +{ +bool ParsePropertyValue(const CustomAssetLibrary::AssetID& asset_id, MaterialProperty::Type type, + const picojson::value& json_value, + std::optional<MaterialProperty::Value>* value) +{ + switch (type) + { + case MaterialProperty::Type::Type_TextureAsset: + { + if (json_value.is<std::string>()) + { + *value = json_value.to_str(); + return true; + } + } + break; + }; + + ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse the json, value is not valid for type '{}'", + asset_id, type); + return false; +} + +bool ParseMaterialProperties(const CustomAssetLibrary::AssetID& asset_id, + const picojson::array& values_data, + std::vector<MaterialProperty>* material_property) +{ + for (const auto& value_data : values_data) + { + VideoCommon::MaterialProperty property; + if (!value_data.is<picojson::object>()) + { + ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse the json, value is not the right json type", + asset_id); + return false; + } + const auto& value_data_obj = value_data.get<picojson::object>(); + + const auto type_iter = value_data_obj.find("type"); + if (type_iter == value_data_obj.end()) + { + ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse the json, value entry 'type' not found", + asset_id); + return false; + } + if (!type_iter->second.is<std::string>()) + { + ERROR_LOG_FMT(VIDEO, + "Asset '{}' failed to parse the json, value entry 'type' is not " + "the right json type", + asset_id); + return false; + } + std::string type = type_iter->second.to_str(); + Common::ToLower(&type); + if (type == "texture_asset") + { + property.m_type = MaterialProperty::Type::Type_TextureAsset; + } + else + { + ERROR_LOG_FMT(VIDEO, + "Asset '{}' failed to parse the json, value entry 'type' is " + "an invalid option", + asset_id); + return false; + } + + const auto code_name_iter = value_data_obj.find("code_name"); + if (code_name_iter == value_data_obj.end()) + { + ERROR_LOG_FMT(VIDEO, + "Asset '{}' failed to parse the json, value entry " + "'code_name' not found", + asset_id); + return false; + } + if (!code_name_iter->second.is<std::string>()) + { + ERROR_LOG_FMT(VIDEO, + "Asset '{}' failed to parse the json, value entry 'code_name' is not " + "the right json type", + asset_id); + return false; + } + property.m_code_name = code_name_iter->second.to_str(); + + const auto value_iter = value_data_obj.find("value"); + if (value_iter != value_data_obj.end()) + { + if (!ParsePropertyValue(asset_id, property.m_type, value_iter->second, &property.m_value)) + return false; + } + + material_property->push_back(std::move(property)); + } + + return true; +} +} // namespace +bool MaterialData::FromJson(const CustomAssetLibrary::AssetID& asset_id, + const picojson::object& json, MaterialData* data) +{ + const auto values_iter = json.find("values"); + if (values_iter == json.end()) + { + ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, 'values' not found", asset_id); + return false; + } + if (!values_iter->second.is<picojson::array>()) + { + ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, 'values' is not the right json type", + asset_id); + return false; + } + const auto& values_array = values_iter->second.get<picojson::array>(); + + if (!ParseMaterialProperties(asset_id, values_array, &data->properties)) + return false; + + const auto shader_asset_iter = json.find("shader_asset"); + if (shader_asset_iter == json.end()) + { + ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, 'shader_asset' not found", asset_id); + return false; + } + if (!shader_asset_iter->second.is<std::string>()) + { + ERROR_LOG_FMT(VIDEO, + "Asset '{}' failed to parse json, 'shader_asset' is not the right json type", + asset_id); + return false; + } + data->shader_asset = shader_asset_iter->second.to_str(); + + return true; +} + +CustomAssetLibrary::LoadInfo MaterialAsset::LoadImpl(const CustomAssetLibrary::AssetID& asset_id) +{ + auto potential_data = std::make_shared<MaterialData>(); + const auto loaded_info = m_owning_library->LoadMaterial(asset_id, potential_data.get()); + if (loaded_info.m_bytes_loaded == 0) + return {}; + { + std::lock_guard lk(m_data_lock); + m_loaded = true; + m_data = std::move(potential_data); + } + return loaded_info; +} +} // namespace VideoCommon |
