diff --git a/docs/SupportedAssetTypes.md b/docs/SupportedAssetTypes.md index aa503afb..86ae5e34 100644 --- a/docs/SupportedAssetTypes.md +++ b/docs/SupportedAssetTypes.md @@ -26,7 +26,7 @@ The following section specify which assets are supported to be dumped to disk (u | GameWorldMp | ❌ | ❌ | | | MapEnts | ✅ | ❌ | | | GfxWorld | ❌ | ❌ | | -| GfxLightDef | ❌ | ❌ | | +| GfxLightDef | ✅ | ✅ | | | Font_s | ❌ | ❌ | | | MenuList | ❌ | ❌ | | | menuDef_t | ❌ | ❌ | | diff --git a/src/ObjLoading/Game/IW3/LightDef/LightDefLoaderIW3.cpp b/src/ObjLoading/Game/IW3/LightDef/LightDefLoaderIW3.cpp new file mode 100644 index 00000000..3bf24bd4 --- /dev/null +++ b/src/ObjLoading/Game/IW3/LightDef/LightDefLoaderIW3.cpp @@ -0,0 +1,77 @@ +#include "LightDefLoaderIW3.h" + +#include "Game/IW3/IW3.h" +#include "LightDef/LightDefCommon.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include + +using namespace IW3; + +namespace +{ + constexpr auto MAX_IMAGE_NAME_SIZE = 0x800; + + class LoaderLightDef final : public AssetCreator + { + public: + LoaderLightDef(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto filename = light_def::GetFileNameForAsset(assetName); + const auto file = m_search_path.Open(filename); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto imageNameSize = file.m_length - sizeof(char) - sizeof(char); + if (imageNameSize < 0 || imageNameSize > MAX_IMAGE_NAME_SIZE) + return AssetCreationResult::Failure(); + + auto* lightDef = m_memory.Alloc(); + lightDef->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, lightDef); + + std::string imageName(static_cast(imageNameSize), '\0'); + + int8_t samplerState; + int8_t lmapLookupStart; + file.m_stream->read(reinterpret_cast(&samplerState), sizeof(int8_t)); + file.m_stream->read(&imageName[0], static_cast(imageNameSize)); + file.m_stream->read(reinterpret_cast(&lmapLookupStart), sizeof(int8_t)); + + auto* imageDependency = context.LoadDependency(imageName); + if (!imageDependency) + { + con::error("Could not load GfxLightDef \"{}\" due to missing image \"{}\"", assetName, imageName); + return AssetCreationResult::Failure(); + } + registration.AddDependency(imageDependency); + + lightDef->attenuation.samplerState = samplerState; + lightDef->attenuation.image = imageDependency->Asset(); + lightDef->lmapLookupStart = static_cast(static_cast(lmapLookupStart)); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace light_def +{ + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace light_def diff --git a/src/ObjLoading/Game/IW3/LightDef/LightDefLoaderIW3.h b/src/ObjLoading/Game/IW3/LightDef/LightDefLoaderIW3.h new file mode 100644 index 00000000..f43da039 --- /dev/null +++ b/src/ObjLoading/Game/IW3/LightDef/LightDefLoaderIW3.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW3/IW3.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace light_def +{ + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath); +} // namespace light_def diff --git a/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp b/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp index f7532754..0289eac4 100644 --- a/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp +++ b/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp @@ -9,6 +9,7 @@ #include "Game/IW3/Techset/PixelShaderLoaderIW3.h" #include "Game/IW3/Techset/VertexShaderLoaderIW3.h" #include "Game/IW3/XModel/LoaderXModelIW3.h" +#include "LightDef/LightDefLoaderIW3.h" #include "Localize/AssetLoaderLocalizeIW3.h" #include "Material/LoaderMaterialIW3.h" #include "ObjLoading.h" @@ -113,7 +114,7 @@ namespace // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); - // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(light_def::CreateLoaderIW3(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); diff --git a/src/ObjWriting/Game/IW3/LightDef/LightDefDumperIW3.cpp b/src/ObjWriting/Game/IW3/LightDef/LightDefDumperIW3.cpp new file mode 100644 index 00000000..4140ec2f --- /dev/null +++ b/src/ObjWriting/Game/IW3/LightDef/LightDefDumperIW3.cpp @@ -0,0 +1,25 @@ +#include "LightDefDumperIW3.h" + +#include "LightDef/LightDefCommon.h" + +using namespace IW3; + +namespace light_def +{ + void DumperIW3::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) + { + const auto* lightDef = asset.Asset(); + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset.m_name)); + + if (!assetFile || lightDef->attenuation.image == nullptr || lightDef->attenuation.image->name == nullptr) + return; + + auto& stream = *assetFile; + + const auto* imageName = lightDef->attenuation.image->name; + if (imageName[0] == ',') + imageName = &imageName[1]; + + stream << lightDef->attenuation.samplerState << imageName << static_cast(lightDef->lmapLookupStart); + } +} // namespace light_def diff --git a/src/ObjWriting/Game/IW3/LightDef/LightDefDumperIW3.h b/src/ObjWriting/Game/IW3/LightDef/LightDefDumperIW3.h new file mode 100644 index 00000000..58e05461 --- /dev/null +++ b/src/ObjWriting/Game/IW3/LightDef/LightDefDumperIW3.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW3/IW3.h" + +namespace light_def +{ + class DumperIW3 final : public AbstractAssetDumper + { + protected: + void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; + }; +} // namespace light_def diff --git a/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp b/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp index e81c2c37..b1dd5eac 100644 --- a/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp +++ b/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp @@ -4,6 +4,7 @@ #include "Game/IW3/Techset/TechsetDumperIW3.h" #include "Game/IW3/XModel/XModelDumperIW3.h" #include "Image/ImageDumperIW3.h" +#include "LightDef/LightDefDumperIW3.h" #include "Localize/LocalizeDumperIW3.h" #include "Maps/MapEntsDumperIW3.h" #include "PhysPreset/PhysPresetInfoStringDumperIW3.h" @@ -37,7 +38,7 @@ void ObjWriter::RegisterAssetDumpers(AssetDumpingContext& context) // REGISTER_DUMPER(AssetDumperGameWorldMp) RegisterAssetDumper(std::make_unique()); // REGISTER_DUMPER(AssetDumperGfxWorld) - // REGISTER_DUMPER(AssetDumperGfxLightDef) + RegisterAssetDumper(std::make_unique()); // REGISTER_DUMPER(AssetDumperFont_s) // REGISTER_DUMPER(AssetDumperMenuList) // REGISTER_DUMPER(AssetDumpermenuDef_t)