diff --git a/docs/SupportedAssetTypes.md b/docs/SupportedAssetTypes.md index aa503afb..f2d9e404 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 | ❌ | ❌ | | @@ -103,7 +103,7 @@ The following section specify which assets are supported to be dumped to disk (u | MapEnts | ❌ | ❌ | | | FxWorld | ❌ | ❌ | | | GfxWorld | ❌ | ❌ | | -| GfxLightDef | ❌ | ❌ | | +| GfxLightDef | ✅ | ✅ | | | Font_s | ❌ | ❌ | | | MenuList | ✅ | ✅ | The output is decompiled. The result will not be the same as the input. | | menuDef_t | ✅ | ✅ | See menulist. | @@ -142,7 +142,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 | ❌ | ❌ | | @@ -179,7 +179,7 @@ The following section specify which assets are supported to be dumped to disk (u | GameWorldMp | ❌ | ❌ | | | MapEnts | ✅ | ❌ | | | GfxWorld | ❌ | ❌ | | -| GfxLightDef | ❌ | ❌ | | +| GfxLightDef | ✅ | ✅ | | | Font_s | ❌ | ❌ | | | FontIcon | ✅ | ✅ | | | MenuList | ❌ | ❌ | | diff --git a/src/ObjLoading/Game/IW3/LightDef/LightDefAssetCreationStateIW3.cpp b/src/ObjLoading/Game/IW3/LightDef/LightDefAssetCreationStateIW3.cpp new file mode 100644 index 00000000..7838e9ed --- /dev/null +++ b/src/ObjLoading/Game/IW3/LightDef/LightDefAssetCreationStateIW3.cpp @@ -0,0 +1,42 @@ +#include "LightDefAssetCreationStateIW3.h" + +#include "Utils/Logging/Log.h" + +using namespace IW3; + +namespace +{ + constexpr auto MAX_LMAP_USAGE = 512; +}; + +LightDefAssetCreationState::LightDefAssetCreationState() + : m_lmap_pixels_used_for_falloff(0) +{ +} + +void LightDefAssetCreationState::SetLightDefLookupStart(GfxLightDef* lightDef, AssetCreationContext& context) +{ + const auto* image = lightDef->attenuation.image; + if (!image) + return; + + // We need the actual image to determine the width, so force load it, if it is a reference + if (image->name && image->name[0] == ',') + { + const auto forceLoadedImage = context.ForceLoadDependency(&image->name[1]); + if (!forceLoadedImage) + return; + + image = forceLoadedImage->Asset(); + } + + const int newLmapUsage = image->width + 2; + if (m_lmap_pixels_used_for_falloff + newLmapUsage > MAX_LMAP_USAGE) + { + con::error( + "Total pixel width of all attenuation textures plus 2 border pixels is {} > {}", m_lmap_pixels_used_for_falloff + newLmapUsage, MAX_LMAP_USAGE); + } + + lightDef->lmapLookupStart = m_lmap_pixels_used_for_falloff + 1; + m_lmap_pixels_used_for_falloff += newLmapUsage; +} diff --git a/src/ObjLoading/Game/IW3/LightDef/LightDefAssetCreationStateIW3.h b/src/ObjLoading/Game/IW3/LightDef/LightDefAssetCreationStateIW3.h new file mode 100644 index 00000000..57e5d55a --- /dev/null +++ b/src/ObjLoading/Game/IW3/LightDef/LightDefAssetCreationStateIW3.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/IZoneAssetCreationState.h" +#include "Game/IW3/IW3.h" + +namespace IW3 +{ + class LightDefAssetCreationState : public IZoneAssetCreationState + { + public: + LightDefAssetCreationState(); + + void SetLightDefLookupStart(GfxLightDef* lightDef, AssetCreationContext& context); + + private: + int m_lmap_pixels_used_for_falloff; + }; +} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/LightDef/LightDefLoaderIW3.cpp b/src/ObjLoading/Game/IW3/LightDef/LightDefLoaderIW3.cpp new file mode 100644 index 00000000..1746d50f --- /dev/null +++ b/src/ObjLoading/Game/IW3/LightDef/LightDefLoaderIW3.cpp @@ -0,0 +1,71 @@ +#include "LightDefLoaderIW3.h" + +#include "Game/IW3/IW3.h" +#include "Game/IW3/LightDef/LightDefAssetCreationStateIW3.h" +#include "LightDef/LightDefCommon.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include + +using namespace IW3; + +namespace +{ + 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(); + + auto* lightDef = m_memory.Alloc(); + lightDef->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, lightDef); + + std::string imageName; + int8_t samplerState; + file.m_stream->read(reinterpret_cast(&samplerState), sizeof(int8_t)); + lightDef->attenuation.samplerState = samplerState; + + std::getline(*file.m_stream, imageName, '\0'); + + 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.image = imageDependency->Asset(); + + context.GetZoneAssetCreationState().SetLightDefLookupStart(lightDef, context); + + 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/ObjLoading/Game/IW4/LightDef/LightDefAssetCreationStateIW4.cpp b/src/ObjLoading/Game/IW4/LightDef/LightDefAssetCreationStateIW4.cpp new file mode 100644 index 00000000..87afdce7 --- /dev/null +++ b/src/ObjLoading/Game/IW4/LightDef/LightDefAssetCreationStateIW4.cpp @@ -0,0 +1,42 @@ +#include "LightDefAssetCreationStateIW4.h" + +#include "Utils/Logging/Log.h" + +using namespace IW4; + +namespace +{ + constexpr auto MAX_LMAP_USAGE = 512; +}; + +LightDefAssetCreationState::LightDefAssetCreationState() + : m_lmap_pixels_used_for_falloff(0) +{ +} + +void LightDefAssetCreationState::SetLightDefLookupStart(GfxLightDef* lightDef, AssetCreationContext& context) +{ + const auto* image = lightDef->attenuation.image; + if (!image) + return; + + // We need the actual image to determine the width, so force load it, if it is a reference + if (image->name && image->name[0] == ',') + { + const auto forceLoadedImage = context.ForceLoadDependency(&image->name[1]); + if (!forceLoadedImage) + return; + + image = forceLoadedImage->Asset(); + } + + const int newLmapUsage = image->width + 2; + if (m_lmap_pixels_used_for_falloff + newLmapUsage > MAX_LMAP_USAGE) + { + con::error( + "Total pixel width of all attenuation textures plus 2 border pixels is {} > {}", m_lmap_pixels_used_for_falloff + newLmapUsage, MAX_LMAP_USAGE); + } + + lightDef->lmapLookupStart = m_lmap_pixels_used_for_falloff + 1; + m_lmap_pixels_used_for_falloff += newLmapUsage; +} diff --git a/src/ObjLoading/Game/IW4/LightDef/LightDefAssetCreationStateIW4.h b/src/ObjLoading/Game/IW4/LightDef/LightDefAssetCreationStateIW4.h new file mode 100644 index 00000000..da7c3607 --- /dev/null +++ b/src/ObjLoading/Game/IW4/LightDef/LightDefAssetCreationStateIW4.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/IZoneAssetCreationState.h" +#include "Game/IW4/IW4.h" + +namespace IW4 +{ + class LightDefAssetCreationState : public IZoneAssetCreationState + { + public: + LightDefAssetCreationState(); + + void SetLightDefLookupStart(GfxLightDef* lightDef, AssetCreationContext& context); + + private: + int m_lmap_pixels_used_for_falloff; + }; +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.cpp b/src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.cpp index f4722b58..fafe6660 100644 --- a/src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.cpp +++ b/src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.cpp @@ -1,6 +1,7 @@ #include "LightDefLoaderIW4.h" #include "Game/IW4/IW4.h" +#include "Game/IW4/LightDef/LightDefAssetCreationStateIW4.h" #include "LightDef/LightDefCommon.h" #include "Utils/Logging/Log.h" @@ -12,8 +13,6 @@ using namespace IW4; namespace { - constexpr auto MAX_IMAGE_NAME_SIZE = 0x800; - class LoaderLightDef final : public AssetCreator { public: @@ -30,22 +29,17 @@ namespace 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'); - + std::string imageName; 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)); + lightDef->attenuation.samplerState = samplerState; + + std::getline(*file.m_stream, imageName, '\0'); auto* imageDependency = context.LoadDependency(imageName); if (!imageDependency) @@ -55,9 +49,9 @@ namespace } registration.AddDependency(imageDependency); - lightDef->attenuation.samplerState = samplerState; lightDef->attenuation.image = imageDependency->Asset(); - lightDef->lmapLookupStart = static_cast(static_cast(lmapLookupStart)); + + context.GetZoneAssetCreationState().SetLightDefLookupStart(lightDef, context); return AssetCreationResult::Success(context.AddAsset(std::move(registration))); } diff --git a/src/ObjLoading/Game/IW5/LightDef/LightDefAssetCreationStateIW5.cpp b/src/ObjLoading/Game/IW5/LightDef/LightDefAssetCreationStateIW5.cpp new file mode 100644 index 00000000..5000ddf0 --- /dev/null +++ b/src/ObjLoading/Game/IW5/LightDef/LightDefAssetCreationStateIW5.cpp @@ -0,0 +1,42 @@ +#include "LightDefAssetCreationStateIW5.h" + +#include "Utils/Logging/Log.h" + +using namespace IW5; + +namespace +{ + constexpr auto MAX_LMAP_USAGE = 512; +}; + +LightDefAssetCreationState::LightDefAssetCreationState() + : m_lmap_pixels_used_for_falloff(0) +{ +} + +void LightDefAssetCreationState::SetLightDefLookupStart(GfxLightDef* lightDef, AssetCreationContext& context) +{ + const auto* image = lightDef->attenuation.image; + if (!image) + return; + + // We need the actual image to determine the width, so force load it, if it is a reference + if (image->name && image->name[0] == ',') + { + const auto forceLoadedImage = context.ForceLoadDependency(&image->name[1]); + if (!forceLoadedImage) + return; + + image = forceLoadedImage->Asset(); + } + + const int newLmapUsage = image->width + 2; + if (m_lmap_pixels_used_for_falloff + newLmapUsage > MAX_LMAP_USAGE) + { + con::error( + "Total pixel width of all attenuation textures plus 2 border pixels is {} > {}", m_lmap_pixels_used_for_falloff + newLmapUsage, MAX_LMAP_USAGE); + } + + lightDef->lmapLookupStart = m_lmap_pixels_used_for_falloff + 1; + m_lmap_pixels_used_for_falloff += newLmapUsage; +} diff --git a/src/ObjLoading/Game/IW5/LightDef/LightDefAssetCreationStateIW5.h b/src/ObjLoading/Game/IW5/LightDef/LightDefAssetCreationStateIW5.h new file mode 100644 index 00000000..d38fd985 --- /dev/null +++ b/src/ObjLoading/Game/IW5/LightDef/LightDefAssetCreationStateIW5.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/IZoneAssetCreationState.h" +#include "Game/IW5/IW5.h" + +namespace IW5 +{ + class LightDefAssetCreationState : public IZoneAssetCreationState + { + public: + LightDefAssetCreationState(); + + void SetLightDefLookupStart(GfxLightDef* lightDef, AssetCreationContext& context); + + private: + int m_lmap_pixels_used_for_falloff; + }; +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/LightDef/LightDefLoaderIW5.cpp b/src/ObjLoading/Game/IW5/LightDef/LightDefLoaderIW5.cpp new file mode 100644 index 00000000..cae04945 --- /dev/null +++ b/src/ObjLoading/Game/IW5/LightDef/LightDefLoaderIW5.cpp @@ -0,0 +1,88 @@ +#include "LightDefLoaderIW5.h" + +#include "Game/IW5/IW5.h" +#include "Game/IW5/LightDef/LightDefAssetCreationStateIW5.h" +#include "LightDef/LightDefCommon.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include +#include + +using namespace IW5; + +namespace +{ + 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(); + + auto* lightDef = m_memory.Alloc(); + lightDef->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, lightDef); + + int8_t attenuationSamplerState; + file.m_stream->read(reinterpret_cast(&attenuationSamplerState), sizeof(int8_t)); + lightDef->attenuation.samplerState = attenuationSamplerState; + + std::string attenuationName; + std::getline(*file.m_stream, attenuationName, '\0'); + auto* attenuationImageDependency = context.LoadDependency(attenuationName); + if (!attenuationImageDependency) + { + con::error("Could not load GfxLightDef \"{}\" due to missing attenuation image \"{}\"", assetName, attenuationName); + return AssetCreationResult::Failure(); + } + registration.AddDependency(attenuationImageDependency); + lightDef->attenuation.image = attenuationImageDependency->Asset(); + + int8_t cucolorisSamplerState; + file.m_stream->read(reinterpret_cast(&cucolorisSamplerState), sizeof(int8_t)); + lightDef->cucoloris.samplerState = cucolorisSamplerState; + + std::string cucolorisName; + std::getline(*file.m_stream, cucolorisName, '\0'); + if (!cucolorisName.empty()) + { + auto* cucolorisImageDependency = context.LoadDependency(cucolorisName); + if (!cucolorisImageDependency) + { + con::warn("Could not load GfxLightDef \"{}\" due to missing cucoloris image \"{}\"", assetName, cucolorisName); + return AssetCreationResult::Failure(); + } + registration.AddDependency(cucolorisImageDependency); + lightDef->cucoloris.image = cucolorisImageDependency->Asset(); + } + + context.GetZoneAssetCreationState().SetLightDefLookupStart(lightDef, context); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace light_def +{ + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace light_def diff --git a/src/ObjLoading/Game/IW5/LightDef/LightDefLoaderIW5.h b/src/ObjLoading/Game/IW5/LightDef/LightDefLoaderIW5.h new file mode 100644 index 00000000..07f0454a --- /dev/null +++ b/src/ObjLoading/Game/IW5/LightDef/LightDefLoaderIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace light_def +{ + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace light_def diff --git a/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp b/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp index a015ee7d..2b5ada65 100644 --- a/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp +++ b/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp @@ -10,6 +10,7 @@ #include "Game/IW5/Techset/VertexShaderLoaderIW5.h" #include "Game/IW5/XModel/LoaderXModelIW5.h" #include "Leaderboard/LoaderLeaderboardIW5.h" +#include "LightDef/LightDefLoaderIW5.h" #include "Localize/LoaderLocalizeIW5.h" #include "Material/LoaderMaterialIW5.h" #include "Menu/LoaderMenuListIW5.h" @@ -151,7 +152,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::CreateLoaderIW5(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); collection.AddAssetCreator(menu::CreateMenuListLoaderIW5(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); diff --git a/src/ObjLoading/Game/T5/LightDef/LightDefLoaderT5.cpp b/src/ObjLoading/Game/T5/LightDef/LightDefLoaderT5.cpp new file mode 100644 index 00000000..6da541d5 --- /dev/null +++ b/src/ObjLoading/Game/T5/LightDef/LightDefLoaderT5.cpp @@ -0,0 +1,69 @@ +#include "LightDefLoaderT5.h" + +#include "Game/T5/T5.h" +#include "LightDef/LightDefCommon.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include + +using namespace T5; + +namespace +{ + 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(); + + auto* lightDef = m_memory.Alloc(); + lightDef->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, lightDef); + + std::string attenuationName; + int8_t samplerState; + file.m_stream->read(reinterpret_cast(&samplerState), sizeof(int8_t)); + lightDef->attenuation.samplerState = samplerState; + + std::getline(*file.m_stream, attenuationName, '\0'); + + auto* attenuationImageDependency = context.LoadDependency(attenuationName); + if (!attenuationImageDependency) + { + con::error("Could not load GfxLightDef \"{}\" due to missing attenuation image \"{}\"", assetName, attenuationName); + return AssetCreationResult::Failure(); + } + registration.AddDependency(attenuationImageDependency); + + lightDef->attenuation.image = attenuationImageDependency->Asset(); + lightDef->lmapLookupStart = 0; + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace light_def +{ + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace light_def diff --git a/src/ObjLoading/Game/T5/LightDef/LightDefLoaderT5.h b/src/ObjLoading/Game/T5/LightDef/LightDefLoaderT5.h new file mode 100644 index 00000000..2583dd21 --- /dev/null +++ b/src/ObjLoading/Game/T5/LightDef/LightDefLoaderT5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T5/T5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace light_def +{ + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace light_def diff --git a/src/ObjLoading/Game/T5/ObjLoaderT5.cpp b/src/ObjLoading/Game/T5/ObjLoaderT5.cpp index 2c72f5c1..e39247d5 100644 --- a/src/ObjLoading/Game/T5/ObjLoaderT5.cpp +++ b/src/ObjLoading/Game/T5/ObjLoaderT5.cpp @@ -9,6 +9,7 @@ #include "Game/T5/Techset/PixelShaderLoaderT5.h" #include "Game/T5/Techset/VertexShaderLoaderT5.h" #include "Game/T5/XModel/LoaderXModelT5.h" +#include "LightDef/LightDefLoaderT5.h" #include "Localize/LoaderLocalizeT5.h" #include "Material/LoaderMaterialT5.h" #include "ObjLoading.h" @@ -125,7 +126,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::CreateLoaderT5(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); diff --git a/src/ObjLoading/Game/T6/LightDef/LightDefLoaderT6.cpp b/src/ObjLoading/Game/T6/LightDef/LightDefLoaderT6.cpp new file mode 100644 index 00000000..04aab6e7 --- /dev/null +++ b/src/ObjLoading/Game/T6/LightDef/LightDefLoaderT6.cpp @@ -0,0 +1,69 @@ +#include "LightDefLoaderT6.h" + +#include "Game/T6/T6.h" +#include "LightDef/LightDefCommon.h" +#include "Utils/Logging/Log.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + 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(); + + auto* lightDef = m_memory.Alloc(); + lightDef->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, lightDef); + + std::string attenuationName; + int8_t samplerState; + file.m_stream->read(reinterpret_cast(&samplerState), sizeof(int8_t)); + lightDef->attenuation.samplerState = samplerState; + + std::getline(*file.m_stream, attenuationName, '\0'); + + auto* attenuationImageDependency = context.LoadDependency(attenuationName); + if (!attenuationImageDependency) + { + con::error("Could not load GfxLightDef \"{}\" due to missing attenuation image \"{}\"", assetName, attenuationName); + return AssetCreationResult::Failure(); + } + registration.AddDependency(attenuationImageDependency); + + lightDef->attenuation.image = attenuationImageDependency->Asset(); + lightDef->lmapLookupStart = 0; + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace light_def +{ + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace light_def diff --git a/src/ObjLoading/Game/T6/LightDef/LightDefLoaderT6.h b/src/ObjLoading/Game/T6/LightDef/LightDefLoaderT6.h new file mode 100644 index 00000000..b4377299 --- /dev/null +++ b/src/ObjLoading/Game/T6/LightDef/LightDefLoaderT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace light_def +{ + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace light_def diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index 97c9128b..0721c573 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -17,6 +17,7 @@ #include "Image/IwiTypes.h" #include "Image/Texture.h" #include "Leaderboard/JsonLoaderLeaderboardT6.h" +#include "LightDef/LightDefLoaderT6.h" #include "Localize/LocalizeLoaderT6.h" #include "Material/LoaderMaterialT6.h" #include "ObjContainer/IPak/IPak.h" @@ -399,7 +400,7 @@ namespace T6 // 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::CreateLoaderT6(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); collection.AddAssetCreator(font_icon::CreateCsvLoaderT6(memory, searchPath)); collection.AddAssetCreator(font_icon::CreateJsonLoaderT6(memory, searchPath)); diff --git a/src/ObjWriting/Game/IW3/LightDef/LightDefDumperIW3.cpp b/src/ObjWriting/Game/IW3/LightDef/LightDefDumperIW3.cpp new file mode 100644 index 00000000..47e45684 --- /dev/null +++ b/src/ObjWriting/Game/IW3/LightDef/LightDefDumperIW3.cpp @@ -0,0 +1,33 @@ +#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) + { + con::error("Could not open GfxLightDef file for dumping!"); + return; + } + + if (lightDef->attenuation.image == nullptr || lightDef->attenuation.image->name == nullptr) + { + con::error("GfxLightDef attenuation data was invalid!"); + return; + } + + auto& stream = *assetFile; + + const auto* imageName = lightDef->attenuation.image->name; + if (imageName[0] == ',') + imageName = &imageName[1]; + + stream << lightDef->attenuation.samplerState << imageName << '\0'; + } +} // 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) diff --git a/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.cpp b/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.cpp index 3806cddf..208aac0f 100644 --- a/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.cpp +++ b/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.cpp @@ -10,9 +10,17 @@ namespace light_def { 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) + if (!assetFile) + { + con::error("Could not open GfxLightDef file for dumping!"); return; + } + + if (lightDef->attenuation.image == nullptr || lightDef->attenuation.image->name == nullptr) + { + con::error("GfxLightDef attenuation data was invalid!"); + return; + } auto& stream = *assetFile; @@ -20,6 +28,6 @@ namespace light_def if (imageName[0] == ',') imageName = &imageName[1]; - stream << lightDef->attenuation.samplerState << imageName << static_cast(lightDef->lmapLookupStart); + stream << lightDef->attenuation.samplerState << imageName << '\0'; } } // namespace light_def diff --git a/src/ObjWriting/Game/IW5/LightDef/LightDefDumperIW5.cpp b/src/ObjWriting/Game/IW5/LightDef/LightDefDumperIW5.cpp new file mode 100644 index 00000000..3abd8e09 --- /dev/null +++ b/src/ObjWriting/Game/IW5/LightDef/LightDefDumperIW5.cpp @@ -0,0 +1,43 @@ +#include "LightDefDumperIW5.h" + +#include "LightDef/LightDefCommon.h" + +#include + +using namespace IW5; + +namespace light_def +{ + void DumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) + { + const auto* lightDef = asset.Asset(); + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset.m_name)); + if (!assetFile) + { + con::error("Could not open GfxLightDef file for dumping!"); + return; + } + + if (lightDef->attenuation.image == nullptr || lightDef->attenuation.image->name == nullptr) + { + con::error("GfxLightDef attenuation data was invalid!"); + return; + } + + auto& stream = *assetFile; + + const auto* attenuationImageName = lightDef->attenuation.image->name; + if (attenuationImageName && attenuationImageName[0] == ',') + attenuationImageName = &attenuationImageName[1]; + + const auto* cucolorisImageName = ""; + if (lightDef->cucoloris.image && lightDef->cucoloris.image->name) + { + cucolorisImageName = lightDef->cucoloris.image->name; + if (cucolorisImageName && cucolorisImageName[0] == ',') + cucolorisImageName = &cucolorisImageName[1]; + } + + stream << lightDef->attenuation.samplerState << attenuationImageName << '\0' << lightDef->cucoloris.samplerState << cucolorisImageName << '\0'; + } +} // namespace light_def diff --git a/src/ObjWriting/Game/IW5/LightDef/LightDefDumperIW5.h b/src/ObjWriting/Game/IW5/LightDef/LightDefDumperIW5.h new file mode 100644 index 00000000..bf325e76 --- /dev/null +++ b/src/ObjWriting/Game/IW5/LightDef/LightDefDumperIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace light_def +{ + class DumperIW5 final : public AbstractAssetDumper + { + protected: + void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; + }; +} // namespace light_def diff --git a/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp b/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp index 92e33973..db308f2f 100644 --- a/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp +++ b/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp @@ -7,6 +7,7 @@ #include "Game/IW5/XModel/XModelDumperIW5.h" #include "Image/ImageDumperIW5.h" #include "Leaderboard/LeaderboardJsonDumperIW5.h" +#include "LightDef/LightDefDumperIW5.h" #include "Localize/LocalizeDumperIW5.h" #include "Maps/AddonMapEntsDumperIW5.h" #include "Menu/MenuDumperIW5.h" @@ -51,7 +52,7 @@ void ObjWriter::RegisterAssetDumpers(AssetDumpingContext& context) // REGISTER_DUMPER(AssetDumperMapEnts) // REGISTER_DUMPER(AssetDumperFxWorld) // REGISTER_DUMPER(AssetDumperGfxWorld) - // REGISTER_DUMPER(AssetDumperGfxLightDef) + RegisterAssetDumper(std::make_unique()); // REGISTER_DUMPER(AssetDumperFont_s) RegisterAssetDumper(std::make_unique()); RegisterAssetDumper(std::make_unique()); diff --git a/src/ObjWriting/Game/T5/LightDef/LightDefDumperT5.cpp b/src/ObjWriting/Game/T5/LightDef/LightDefDumperT5.cpp new file mode 100644 index 00000000..37572774 --- /dev/null +++ b/src/ObjWriting/Game/T5/LightDef/LightDefDumperT5.cpp @@ -0,0 +1,33 @@ +#include "LightDefDumperT5.h" + +#include "LightDef/LightDefCommon.h" + +using namespace T5; + +namespace light_def +{ + void DumperT5::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) + { + const auto* lightDef = asset.Asset(); + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset.m_name)); + if (!assetFile) + { + con::error("Could not open GfxLightDef file for dumping!"); + return; + } + + if (lightDef->attenuation.image == nullptr || lightDef->attenuation.image->name == nullptr) + { + con::error("GfxLightDef attenuation data was invalid!"); + return; + } + + auto& stream = *assetFile; + + const auto* imageName = lightDef->attenuation.image->name; + if (imageName[0] == ',') + imageName = &imageName[1]; + + stream << lightDef->attenuation.samplerState << imageName << '\0'; + } +} // namespace light_def diff --git a/src/ObjWriting/Game/T5/LightDef/LightDefDumperT5.h b/src/ObjWriting/Game/T5/LightDef/LightDefDumperT5.h new file mode 100644 index 00000000..0829d63d --- /dev/null +++ b/src/ObjWriting/Game/T5/LightDef/LightDefDumperT5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T5/T5.h" + +namespace light_def +{ + class DumperT5 final : public AbstractAssetDumper + { + protected: + void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; + }; +} // namespace light_def diff --git a/src/ObjWriting/Game/T5/ObjWriterT5.cpp b/src/ObjWriting/Game/T5/ObjWriterT5.cpp index 4e23d39d..9250df8a 100644 --- a/src/ObjWriting/Game/T5/ObjWriterT5.cpp +++ b/src/ObjWriting/Game/T5/ObjWriterT5.cpp @@ -4,6 +4,7 @@ #include "Game/T5/Techset/TechsetDumperT5.h" #include "Game/T5/XModel/XModelDumperT5.h" #include "Image/ImageDumperT5.h" +#include "LightDef/LightDefDumperT5.h" #include "Localize/LocalizeDumperT5.h" #include "PhysPreset/PhysPresetInfoStringDumperT5.h" #include "RawFile/RawFileDumperT5.h" @@ -35,7 +36,7 @@ void ObjWriter::RegisterAssetDumpers(AssetDumpingContext& context) // REGISTER_DUMPER(AssetDumperGameWorldMp, m_game_world_mp) // REGISTER_DUMPER(AssetDumperMapEnts, m_map_ents) // REGISTER_DUMPER(AssetDumperGfxWorld, m_gfx_world) - // REGISTER_DUMPER(AssetDumperGfxLightDef, m_gfx_light_def) + RegisterAssetDumper(std::make_unique()); // REGISTER_DUMPER(AssetDumperFont, m_font) // REGISTER_DUMPER(AssetDumperMenuList, m_menu_list) // REGISTER_DUMPER(AssetDumperMenuDef, m_menu_def) diff --git a/src/ObjWriting/Game/T6/LightDef/LightDefDumperT6.cpp b/src/ObjWriting/Game/T6/LightDef/LightDefDumperT6.cpp new file mode 100644 index 00000000..d3b4f370 --- /dev/null +++ b/src/ObjWriting/Game/T6/LightDef/LightDefDumperT6.cpp @@ -0,0 +1,33 @@ +#include "LightDefDumperT6.h" + +#include "LightDef/LightDefCommon.h" + +using namespace T6; + +namespace light_def +{ + void DumperT6::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) + { + const auto* lightDef = asset.Asset(); + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset.m_name)); + if (!assetFile) + { + con::error("Could not open GfxLightDef file for dumping!"); + return; + } + + if (lightDef->attenuation.image == nullptr || lightDef->attenuation.image->name == nullptr) + { + con::error("GfxLightDef attenuation data was invalid!"); + return; + } + + auto& stream = *assetFile; + + const auto* imageName = lightDef->attenuation.image->name; + if (imageName[0] == ',') + imageName = &imageName[1]; + + stream << lightDef->attenuation.samplerState << imageName << '\0'; + } +} // namespace light_def diff --git a/src/ObjWriting/Game/T6/LightDef/LightDefDumperT6.h b/src/ObjWriting/Game/T6/LightDef/LightDefDumperT6.h new file mode 100644 index 00000000..eddd5289 --- /dev/null +++ b/src/ObjWriting/Game/T6/LightDef/LightDefDumperT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace light_def +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; + }; +} // namespace light_def diff --git a/src/ObjWriting/Game/T6/ObjWriterT6.cpp b/src/ObjWriting/Game/T6/ObjWriterT6.cpp index f4d09da2..aa3cb9b1 100644 --- a/src/ObjWriting/Game/T6/ObjWriterT6.cpp +++ b/src/ObjWriting/Game/T6/ObjWriterT6.cpp @@ -6,6 +6,7 @@ #include "Game/T6/XModel/XModelDumperT6.h" #include "Image/ImageDumperT6.h" #include "Leaderboard/LeaderboardJsonDumperT6.h" +#include "LightDef/LightDefDumperT6.h" #include "Localize/LocalizeDumperT6.h" #include "Maps/MapEntsDumperT6.h" #include "PhysConstraints/PhysConstraintsInfoStringDumperT6.h" @@ -51,7 +52,7 @@ void ObjWriter::RegisterAssetDumpers(AssetDumpingContext& context) // REGISTER_DUMPER(AssetDumperGameWorldMp, m_game_world_mp) RegisterAssetDumper(std::make_unique()); // REGISTER_DUMPER(AssetDumperGfxWorld, m_gfx_world) - // REGISTER_DUMPER(AssetDumperGfxLightDef, m_gfx_light_def) + RegisterAssetDumper(std::make_unique()); // REGISTER_DUMPER(AssetDumperFont, m_font) RegisterAssetDumper(font_icon::CreateDumperT6()); // REGISTER_DUMPER(AssetDumperMenuList, m_menu_list)