179 lines
5.1 KiB
C++
Raw Normal View History

2022-02-27 12:53:44 +00:00
#include <STDInclude.hpp>
#include "IMaterial.hpp"
2017-01-19 22:23:59 +01:00
namespace Assets
{
2018-12-17 14:29:18 +01:00
void IMaterial::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
2017-01-19 22:23:59 +01:00
{
if (!header->data) this->loadFromDisk(header, name, builder); // Check if we want to load a material from disk
2017-01-19 22:23:59 +01:00
if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one
assert(header->data);
2022-12-14 09:40:15 +01:00
}
void IMaterial::loadFromDisk(Game::XAssetHeader* header, const std::string& name, [[maybe_unused]] Components::ZoneBuilder::Zone* builder)
2022-12-14 09:40:15 +01:00
{
header->material = builder->getIW4OfApi()->read<Game::Material>(Game::XAssetType::ASSET_TYPE_MATERIAL, name);
2017-01-19 22:23:59 +01:00
}
2018-12-17 14:29:18 +01:00
void IMaterial::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/)
2017-01-19 22:23:59 +01:00
{
header->material = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).material;
}
void IMaterial::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{
Game::Material* asset = header.material;
if (asset->techniqueSet)
{
builder->loadAsset(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, asset->techniqueSet);
}
if (asset->textureTable)
{
for (char i = 0; i < asset->textureCount; ++i)
{
2018-05-09 14:33:52 +02:00
if (asset->textureTable[i].u.image)
2017-01-19 22:23:59 +01:00
{
2022-12-14 09:40:15 +01:00
if (asset->textureTable[i].semantic == Game::TextureSemantic::TS_WATER_MAP)
2017-01-19 22:23:59 +01:00
{
2018-05-09 14:33:52 +02:00
if (asset->textureTable[i].u.water->image)
2017-01-19 22:23:59 +01:00
{
2018-05-09 14:33:52 +02:00
builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->textureTable[i].u.water->image);
2017-01-19 22:23:59 +01:00
}
}
else
{
2018-05-09 14:33:52 +02:00
builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->textureTable[i].u.image);
2017-01-19 22:23:59 +01:00
}
}
}
}
}
void IMaterial::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{
AssertSize(Game::Material, 96);
Utils::Stream* buffer = builder->getBuffer();
Game::Material* asset = header.material;
Game::Material* dest = buffer->dest<Game::Material>();
buffer->save(asset);
buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL);
2018-05-09 14:33:52 +02:00
if (asset->info.name)
2017-01-19 22:23:59 +01:00
{
2018-05-09 14:33:52 +02:00
buffer->saveString(builder->getAssetName(this->getType(), asset->info.name));
Utils::Stream::ClearPointer(&dest->info.name);
2017-01-19 22:23:59 +01:00
}
if (asset->techniqueSet)
{
dest->techniqueSet = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, asset->techniqueSet).techniqueSet;
}
if (asset->textureTable)
{
AssertSize(Game::MaterialTextureDef, 12);
// Pointer/Offset insertion is untested, but it worked in T6, so I think it's fine
if (builder->hasPointer(asset->textureTable))
{
dest->textureTable = builder->getPointer(asset->textureTable);
}
else
{
buffer->align(Utils::Stream::ALIGN_4);
builder->storePointer(asset->textureTable);
auto* destTextureTable = buffer->dest<Game::MaterialTextureDef>();
2017-01-19 22:23:59 +01:00
buffer->saveArray(asset->textureTable, asset->textureCount);
for (std::uint8_t i = 0; i < asset->textureCount; ++i)
2017-01-19 22:23:59 +01:00
{
auto* destTextureDef = &destTextureTable[i];
auto* textureDef = &asset->textureTable[i];
2017-01-19 22:23:59 +01:00
2022-12-14 09:40:15 +01:00
if (textureDef->semantic == Game::TextureSemantic::TS_WATER_MAP)
2017-01-19 22:23:59 +01:00
{
AssertSize(Game::water_t, 68);
Game::water_t* destWater = buffer->dest<Game::water_t>();
2018-05-09 14:33:52 +02:00
Game::water_t* water = textureDef->u.water;
2017-01-19 22:23:59 +01:00
if (water)
{
buffer->align(Utils::Stream::ALIGN_4);
buffer->save(water);
2018-05-09 14:33:52 +02:00
Utils::Stream::ClearPointer(&destTextureDef->u.water);
2017-01-19 22:23:59 +01:00
// Save_water_t
if (water->H0)
{
buffer->align(Utils::Stream::ALIGN_4);
buffer->save(water->H0, 8, water->M * water->N);
Utils::Stream::ClearPointer(&destWater->H0);
}
if (water->wTerm)
{
buffer->align(Utils::Stream::ALIGN_4);
buffer->save(water->wTerm, 4, water->M * water->N);
Utils::Stream::ClearPointer(&destWater->wTerm);
}
if (water->image)
{
destWater->image = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, water->image).image;
}
}
}
2018-05-09 14:33:52 +02:00
else if (textureDef->u.image)
2017-01-19 22:23:59 +01:00
{
2018-05-09 14:33:52 +02:00
destTextureDef->u.image = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, textureDef->u.image).image;
2017-01-19 22:23:59 +01:00
}
}
Utils::Stream::ClearPointer(&dest->textureTable);
}
}
if (asset->constantTable)
{
AssertSize(Game::MaterialConstantDef, 32);
if (builder->hasPointer(asset->constantTable))
{
dest->constantTable = builder->getPointer(asset->constantTable);
}
else
{
buffer->align(Utils::Stream::ALIGN_16);
builder->storePointer(asset->constantTable);
buffer->saveArray(asset->constantTable, asset->constantCount);
Utils::Stream::ClearPointer(&dest->constantTable);
}
}
2018-05-09 14:33:52 +02:00
if (asset->stateBitsTable)
2017-01-19 22:23:59 +01:00
{
2018-05-09 14:33:52 +02:00
if (builder->hasPointer(asset->stateBitsTable))
2017-01-19 22:23:59 +01:00
{
2018-05-09 14:33:52 +02:00
dest->stateBitsTable = builder->getPointer(asset->stateBitsTable);
2017-01-19 22:23:59 +01:00
}
else
{
buffer->align(Utils::Stream::ALIGN_4);
2018-05-09 14:33:52 +02:00
builder->storePointer(asset->stateBitsTable);
2017-01-19 22:23:59 +01:00
2018-05-09 14:33:52 +02:00
buffer->save(asset->stateBitsTable, 8, asset->stateBitsCount);
Utils::Stream::ClearPointer(&dest->stateBitsTable);
2017-01-19 22:23:59 +01:00
}
}
buffer->popBlock();
}
}