basics of material gdt dumping

This commit is contained in:
Jan 2022-04-22 23:21:39 +02:00
parent bba96b248d
commit cd34f8db39
2 changed files with 145 additions and 49 deletions

View File

@ -353,6 +353,23 @@ namespace IW3
return json(ss.str());
}
json BuildGameFlagsJson(const unsigned char gameFlags)
{
std::vector<std::string> values;
for (auto i = 0u; i < (sizeof(gameFlags) * 8u); i++)
{
if (gameFlags & (1 << i))
{
std::ostringstream ss;
ss << "0x" << std::hex << (1 << i);
values.emplace_back(ss.str());
}
}
return json(values);
}
}
bool AssetDumperMaterial::ShouldDump(XAssetInfo<Material>* asset)
@ -427,7 +444,7 @@ void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Mat
const json j = {
{
"info", {
{"gameFlags", material->info.gameFlags}, // TODO: Find out what gameflags mean
{"gameFlags", BuildGameFlagsJson(material->info.gameFlags)}, // TODO: Find out what gameflags mean
{"sortKey", foundSortKeyName != sortKeyNames.end() ? foundSortKeyName->second : std::to_string(material->info.sortKey)},
{"textureAtlasRowCount", material->info.textureAtlasRowCount},
{"textureAtlasColumnCount", material->info.textureAtlasColumnCount},

View File

@ -2,6 +2,7 @@
#include <iomanip>
#include <sstream>
#include <type_traits>
#include <nlohmann/json.hpp>
#include "Game/IW4/MaterialConstantsIW4.h"
@ -12,6 +13,8 @@ using json = nlohmann::json;
namespace IW4
{
static constexpr auto DUMP_AS_GDT = true;
const char* AssetName(const char* name)
{
if (name && name[0] == ',')
@ -327,10 +330,27 @@ namespace IW4
return jArray;
}
json BuildSurfaceTypeBitsJson(const unsigned surfaceTypeBits)
json BuildCharFlagsJson(const std::string& prefix, const unsigned char gameFlags)
{
std::vector<std::string> values;
for (auto i = 0u; i < (sizeof(gameFlags) * 8u); i++)
{
if (gameFlags & (1 << i))
{
std::ostringstream ss;
ss << prefix << " 0x" << std::hex << (1 << i);
values.emplace_back(ss.str());
}
}
return json(values);
}
std::string CreateSurfaceTypeString(const unsigned surfaceTypeBits)
{
if (!surfaceTypeBits)
return json(surfaceTypeNames[SURF_TYPE_DEFAULT]);
return surfaceTypeNames[SURF_TYPE_DEFAULT];
static constexpr auto NON_SURFACE_TYPE_BITS = ~(std::numeric_limits<unsigned>::max() >> ((sizeof(unsigned) * 8) - (static_cast<unsigned>(SURF_TYPE_NUM) - 1)));
assert((surfaceTypeBits & NON_SURFACE_TYPE_BITS) == 0);
@ -350,30 +370,13 @@ namespace IW4
}
if (firstSurfaceType)
return json(surfaceTypeNames[SURF_TYPE_DEFAULT]);
return surfaceTypeNames[SURF_TYPE_DEFAULT];
return json(ss.str());
return ss.str();
}
}
bool AssetDumperMaterial::ShouldDump(XAssetInfo<Material>* asset)
{
return true;
}
void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset)
{
auto* material = asset->Asset();
std::ostringstream ss;
ss << "materials/" << asset->m_name << ".json";
const auto assetFile = context.OpenAssetFile(ss.str());
if (!assetFile)
return;
auto& stream = *assetFile;
void DumpMaterialAsJson(Material* material, std::ostream& stream)
{
static const char* cameraRegionNames[]
{
"litOpaque",
@ -386,7 +389,7 @@ void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Mat
const json j = {
{
"info", {
{"gameFlags", material->info.gameFlags}, // TODO: Find out what gameflags mean
{"gameFlags", BuildCharFlagsJson("gameFlag", material->info.gameFlags)}, // TODO: Find out what gameflags mean
{"sortKey", material->info.sortKey},
{"textureAtlasRowCount", material->info.textureAtlasRowCount},
{"textureAtlasColumnCount", material->info.textureAtlasColumnCount},
@ -404,12 +407,12 @@ void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Mat
{"primarySortKey", static_cast<unsigned>(material->info.drawSurf.fields.primarySortKey)}
}
},
{"surfaceTypeBits", BuildSurfaceTypeBitsJson(material->info.surfaceTypeBits)},
{"surfaceTypeBits", CreateSurfaceTypeString(material->info.surfaceTypeBits)},
{"hashIndex", material->info.hashIndex}
}
},
{"stateBitsEntry", std::vector(std::begin(material->stateBitsEntry), std::end(material->stateBitsEntry))},
{"stateFlags", material->stateFlags},
{"stateFlags", BuildCharFlagsJson("stateFlag", material->stateFlags)},
{"cameraRegion", ArrayEntry(cameraRegionNames, material->cameraRegion)},
{"techniqueSet", material->techniqueSet && material->techniqueSet->name ? AssetName(material->techniqueSet->name) : nullptr},
{"textureTable", BuildTextureTableJson(material->textureTable, material->textureCount)},
@ -418,4 +421,80 @@ void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Mat
};
stream << std::setw(4) << j;
}
class MaterialGdtDumper
{
std::ostream& m_stream;
GdtEntry m_entry;
void SetValue(const std::string& key, std::string value)
{
m_entry.m_properties.emplace(std::make_pair(key, std::move(value)));
}
template <typename T,
typename = typename std::enable_if_t<std::is_arithmetic_v<T>, T>>
void SetValue(const std::string& key, T value)
{
m_entry.m_properties.emplace(std::make_pair(key, std::to_string(value)));
}
void SetCommonValues(const Material* material)
{
SetValue("textureAtlasRowCount", material->info.textureAtlasRowCount);
SetValue("textureAtlasColumnCount", material->info.textureAtlasColumnCount);
SetValue("surfaceType", CreateSurfaceTypeString(material->info.surfaceTypeBits));
}
public:
explicit MaterialGdtDumper(std::ostream& stream)
: m_stream(stream)
{
m_entry.m_gdf_name = "material.gdf";
}
void Dump(const Material* material)
{
m_entry.m_name = material->info.name;
SetCommonValues(material);
Gdt gdt(GdtVersion("IW4", 1));
gdt.m_entries.emplace_back(std::make_unique<GdtEntry>(std::move(m_entry)));
GdtOutputStream::WriteGdt(gdt, m_stream);
}
};
}
bool AssetDumperMaterial::ShouldDump(XAssetInfo<Material>* asset)
{
return true;
}
void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo<Material>* asset)
{
auto* material = asset->Asset();
std::ostringstream ss;
if (DUMP_AS_GDT)
ss << "materials/" << asset->m_name << ".gdt";
else
ss << "materials/" << asset->m_name << ".json";
const auto assetFile = context.OpenAssetFile(ss.str());
if (!assetFile)
return;
auto& stream = *assetFile;
if (DUMP_AS_GDT)
{
MaterialGdtDumper dumper(stream);
dumper.Dump(material);
}
else
DumpMaterialAsJson(material, stream);
}