mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
refactor: image and obj data loading
This commit is contained in:
parent
5fee875495
commit
5cc52c42cd
@ -1326,7 +1326,6 @@ namespace IW3
|
|||||||
// void/*IDirect3DTexture9*/* map;
|
// void/*IDirect3DTexture9*/* map;
|
||||||
// void/*IDirect3DVolumeTexture9*/* volmap;
|
// void/*IDirect3DVolumeTexture9*/* volmap;
|
||||||
// void/*IDirect3DCubeTexture9*/* cubemap;
|
// void/*IDirect3DCubeTexture9*/* cubemap;
|
||||||
Texture* texture;
|
|
||||||
GfxImageLoadDef* loadDef;
|
GfxImageLoadDef* loadDef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1009,7 +1009,6 @@ namespace IW4
|
|||||||
// IDirect3DTexture9* map;
|
// IDirect3DTexture9* map;
|
||||||
// IDirect3DVolumeTexture9* volmap;
|
// IDirect3DVolumeTexture9* volmap;
|
||||||
// IDirect3DCubeTexture9* cubemap;
|
// IDirect3DCubeTexture9* cubemap;
|
||||||
Texture* texture;
|
|
||||||
GfxImageLoadDef* loadDef;
|
GfxImageLoadDef* loadDef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1143,9 +1143,6 @@ namespace IW5
|
|||||||
// IDirect3DTexture9* map;
|
// IDirect3DTexture9* map;
|
||||||
// IDirect3DVolumeTexture9* volmap;
|
// IDirect3DVolumeTexture9* volmap;
|
||||||
// IDirect3DCubeTexture9* cubemap;
|
// IDirect3DCubeTexture9* cubemap;
|
||||||
#ifndef __ida
|
|
||||||
Texture* texture;
|
|
||||||
#endif
|
|
||||||
GfxImageLoadDef* loadDef;
|
GfxImageLoadDef* loadDef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1024,7 +1024,6 @@ namespace T5
|
|||||||
// IDirect3DTexture9* map;
|
// IDirect3DTexture9* map;
|
||||||
// IDirect3DVolumeTexture9* volmap;
|
// IDirect3DVolumeTexture9* volmap;
|
||||||
// IDirect3DCubeTexture9* cubemap;
|
// IDirect3DCubeTexture9* cubemap;
|
||||||
Texture* texture;
|
|
||||||
GfxImageLoadDef* loadDef;
|
GfxImageLoadDef* loadDef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,62 +2,8 @@
|
|||||||
|
|
||||||
#include "Utils/Pack.h"
|
#include "Utils/Pack.h"
|
||||||
|
|
||||||
#include <cctype>
|
|
||||||
|
|
||||||
using namespace T6;
|
using namespace T6;
|
||||||
|
|
||||||
int Common::Com_HashKey(const char* str, const int maxLen)
|
|
||||||
{
|
|
||||||
if (str == nullptr)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int hash = 0;
|
|
||||||
for (int i = 0; i < maxLen; i++)
|
|
||||||
{
|
|
||||||
if (str[i] == '\0')
|
|
||||||
break;
|
|
||||||
|
|
||||||
hash += str[i] * (0x77 + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash ^ ((hash ^ (hash >> 10)) >> 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Common::Com_HashString(const char* str)
|
|
||||||
{
|
|
||||||
if (!str)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
auto result = 0x1505;
|
|
||||||
auto offset = 0;
|
|
||||||
while (str[offset])
|
|
||||||
{
|
|
||||||
const auto c = tolower(str[offset++]);
|
|
||||||
result = c + 33 * result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Common::Com_HashString(const char* str, const int len)
|
|
||||||
{
|
|
||||||
if (!str)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int result = 0x1505;
|
|
||||||
int offset = 0;
|
|
||||||
while (str[offset])
|
|
||||||
{
|
|
||||||
if (len > 0 && offset >= len)
|
|
||||||
break;
|
|
||||||
|
|
||||||
const int c = tolower(str[offset++]);
|
|
||||||
result = c + 33 * result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackedTexCoords Common::Vec2PackTexCoords(const float (&in)[2])
|
PackedTexCoords Common::Vec2PackTexCoords(const float (&in)[2])
|
||||||
{
|
{
|
||||||
return PackedTexCoords{pack32::Vec2PackTexCoordsUV(in)};
|
return PackedTexCoords{pack32::Vec2PackTexCoordsUV(in)};
|
||||||
|
@ -2,14 +2,64 @@
|
|||||||
|
|
||||||
#include "T6.h"
|
#include "T6.h"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
namespace T6
|
namespace T6
|
||||||
{
|
{
|
||||||
class Common
|
class Common
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static int Com_HashKey(const char* str, int maxLen);
|
static constexpr int Com_HashKey(const char* str, const int maxLen)
|
||||||
static int Com_HashString(const char* str);
|
{
|
||||||
static int Com_HashString(const char* str, int len);
|
if (str == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int hash = 0;
|
||||||
|
for (int i = 0; i < maxLen; i++)
|
||||||
|
{
|
||||||
|
if (str[i] == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
hash += str[i] * (0x77 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash ^ ((hash ^ (hash >> 10)) >> 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr int Com_HashString(const char* str)
|
||||||
|
{
|
||||||
|
if (!str)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto result = 0x1505;
|
||||||
|
auto offset = 0;
|
||||||
|
while (str[offset])
|
||||||
|
{
|
||||||
|
const auto c = tolower(str[offset++]);
|
||||||
|
result = c + 33 * result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr int Com_HashString(const char* str, const int len)
|
||||||
|
{
|
||||||
|
if (!str)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int result = 0x1505;
|
||||||
|
int offset = 0;
|
||||||
|
while (str[offset])
|
||||||
|
{
|
||||||
|
if (len > 0 && offset >= len)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const int c = tolower(str[offset++]);
|
||||||
|
result = c + 33 * result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr uint32_t R_HashString(const char* str, uint32_t hash)
|
static constexpr uint32_t R_HashString(const char* str, uint32_t hash)
|
||||||
{
|
{
|
||||||
|
@ -848,7 +848,6 @@ namespace T6
|
|||||||
union GfxTexture
|
union GfxTexture
|
||||||
{
|
{
|
||||||
void /*ID3D11ShaderResourceView*/* basemap;
|
void /*ID3D11ShaderResourceView*/* basemap;
|
||||||
Texture* texture;
|
|
||||||
GfxImageLoadDef* loadDef;
|
GfxImageLoadDef* loadDef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,6 +77,11 @@ uint8_t* Texture::GetBufferForMipLevel(const int mipLevel)
|
|||||||
return GetBufferForMipLevel(mipLevel, 0);
|
return GetBufferForMipLevel(mipLevel, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t* Texture::GetBufferForMipLevel(const int mipLevel) const
|
||||||
|
{
|
||||||
|
return GetBufferForMipLevel(mipLevel, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// ==============================================
|
// ==============================================
|
||||||
// ================ Texture2D ===================
|
// ================ Texture2D ===================
|
||||||
// ==============================================
|
// ==============================================
|
||||||
@ -183,6 +188,31 @@ uint8_t* Texture2D::GetBufferForMipLevel(const int mipLevel, const int face)
|
|||||||
return &m_data[bufferOffset];
|
return &m_data[bufferOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t* Texture2D::GetBufferForMipLevel(const int mipLevel, const int face) const
|
||||||
|
{
|
||||||
|
assert(mipLevel >= 0);
|
||||||
|
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
|
||||||
|
assert(face == 0);
|
||||||
|
assert(m_data);
|
||||||
|
|
||||||
|
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (face != 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (!m_data)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
size_t bufferOffset = 0;
|
||||||
|
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
|
||||||
|
{
|
||||||
|
bufferOffset += GetSizeOfMipLevel(previousMipLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &m_data[bufferOffset];
|
||||||
|
}
|
||||||
|
|
||||||
// ==============================================
|
// ==============================================
|
||||||
// =============== TextureCube ==================
|
// =============== TextureCube ==================
|
||||||
// ==============================================
|
// ==============================================
|
||||||
@ -251,6 +281,32 @@ uint8_t* TextureCube::GetBufferForMipLevel(const int mipLevel, const int face)
|
|||||||
return &m_data[bufferOffset + GetSizeOfMipLevel(mipLevel) * face];
|
return &m_data[bufferOffset + GetSizeOfMipLevel(mipLevel) * face];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t* TextureCube::GetBufferForMipLevel(const int mipLevel, const int face) const
|
||||||
|
{
|
||||||
|
assert(mipLevel >= 0);
|
||||||
|
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
|
||||||
|
assert(face >= 0);
|
||||||
|
assert(face < FACE_COUNT);
|
||||||
|
assert(m_data);
|
||||||
|
|
||||||
|
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (face < 0 || face >= FACE_COUNT)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (!m_data)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
size_t bufferOffset = 0;
|
||||||
|
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
|
||||||
|
{
|
||||||
|
bufferOffset += GetSizeOfMipLevel(previousMipLevel) * FACE_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &m_data[bufferOffset + GetSizeOfMipLevel(mipLevel) * face];
|
||||||
|
}
|
||||||
|
|
||||||
// ==============================================
|
// ==============================================
|
||||||
// ================ Texture3D ===================
|
// ================ Texture3D ===================
|
||||||
// ==============================================
|
// ==============================================
|
||||||
@ -360,3 +416,28 @@ uint8_t* Texture3D::GetBufferForMipLevel(const int mipLevel, const int face)
|
|||||||
|
|
||||||
return &m_data[bufferOffset];
|
return &m_data[bufferOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t* Texture3D::GetBufferForMipLevel(const int mipLevel, const int face) const
|
||||||
|
{
|
||||||
|
assert(mipLevel >= 0);
|
||||||
|
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
|
||||||
|
assert(face == 0);
|
||||||
|
assert(m_data);
|
||||||
|
|
||||||
|
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (face != 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (!m_data)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
size_t bufferOffset = 0;
|
||||||
|
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
|
||||||
|
{
|
||||||
|
bufferOffset += GetSizeOfMipLevel(previousMipLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &m_data[bufferOffset];
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
enum class TextureType
|
enum class TextureType : std::uint8_t
|
||||||
{
|
{
|
||||||
T_2D,
|
T_2D,
|
||||||
T_CUBE,
|
T_CUBE,
|
||||||
@ -28,23 +28,25 @@ public:
|
|||||||
|
|
||||||
Texture& operator=(const Texture& other) = delete;
|
Texture& operator=(const Texture& other) = delete;
|
||||||
|
|
||||||
virtual TextureType GetTextureType() const = 0;
|
[[nodiscard]] virtual TextureType GetTextureType() const = 0;
|
||||||
const ImageFormat* GetFormat() const;
|
[[nodiscard]] const ImageFormat* GetFormat() const;
|
||||||
|
|
||||||
virtual unsigned GetWidth() const = 0;
|
[[nodiscard]] virtual unsigned GetWidth() const = 0;
|
||||||
virtual unsigned GetHeight() const = 0;
|
[[nodiscard]] virtual unsigned GetHeight() const = 0;
|
||||||
virtual unsigned GetDepth() const = 0;
|
[[nodiscard]] virtual unsigned GetDepth() const = 0;
|
||||||
virtual int GetFaceCount() const = 0;
|
[[nodiscard]] virtual int GetFaceCount() const = 0;
|
||||||
|
|
||||||
void Allocate();
|
void Allocate();
|
||||||
bool Empty() const;
|
[[nodiscard]] bool Empty() const;
|
||||||
|
|
||||||
virtual size_t GetSizeOfMipLevel(int mipLevel) const = 0;
|
[[nodiscard]] virtual size_t GetSizeOfMipLevel(int mipLevel) const = 0;
|
||||||
virtual uint8_t* GetBufferForMipLevel(int mipLevel, int face) = 0;
|
[[nodiscard]] virtual uint8_t* GetBufferForMipLevel(int mipLevel, int face) = 0;
|
||||||
uint8_t* GetBufferForMipLevel(int mipLevel);
|
[[nodiscard]] virtual const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const = 0;
|
||||||
|
[[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel);
|
||||||
|
[[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel) const;
|
||||||
|
|
||||||
bool HasMipMaps() const;
|
[[nodiscard]] bool HasMipMaps() const;
|
||||||
virtual int GetMipMapCount() const = 0;
|
[[nodiscard]] virtual int GetMipMapCount() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Texture2D : public Texture
|
class Texture2D : public Texture
|
||||||
@ -63,17 +65,18 @@ public:
|
|||||||
Texture2D& operator=(const Texture2D& other) = delete;
|
Texture2D& operator=(const Texture2D& other) = delete;
|
||||||
Texture2D& operator=(Texture2D&& other) noexcept;
|
Texture2D& operator=(Texture2D&& other) noexcept;
|
||||||
|
|
||||||
TextureType GetTextureType() const override;
|
[[nodiscard]] TextureType GetTextureType() const override;
|
||||||
|
|
||||||
unsigned GetWidth() const override;
|
[[nodiscard]] unsigned GetWidth() const override;
|
||||||
unsigned GetHeight() const override;
|
[[nodiscard]] unsigned GetHeight() const override;
|
||||||
unsigned GetDepth() const override;
|
[[nodiscard]] unsigned GetDepth() const override;
|
||||||
int GetFaceCount() const override;
|
[[nodiscard]] int GetFaceCount() const override;
|
||||||
|
|
||||||
size_t GetSizeOfMipLevel(int mipLevel) const override;
|
[[nodiscard]] size_t GetSizeOfMipLevel(int mipLevel) const override;
|
||||||
uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
|
[[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
|
||||||
|
[[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const override;
|
||||||
|
|
||||||
int GetMipMapCount() const override;
|
[[nodiscard]] int GetMipMapCount() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureCube final : public Texture2D
|
class TextureCube final : public Texture2D
|
||||||
@ -90,11 +93,12 @@ public:
|
|||||||
TextureCube& operator=(const TextureCube& other) = delete;
|
TextureCube& operator=(const TextureCube& other) = delete;
|
||||||
TextureCube& operator=(TextureCube&& other) noexcept;
|
TextureCube& operator=(TextureCube&& other) noexcept;
|
||||||
|
|
||||||
TextureType GetTextureType() const override;
|
[[nodiscard]] TextureType GetTextureType() const override;
|
||||||
|
|
||||||
int GetFaceCount() const override;
|
[[nodiscard]] int GetFaceCount() const override;
|
||||||
|
|
||||||
uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
|
[[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
|
||||||
|
[[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Texture3D final : public Texture
|
class Texture3D final : public Texture
|
||||||
@ -113,15 +117,16 @@ public:
|
|||||||
Texture3D& operator=(const Texture3D& other) = delete;
|
Texture3D& operator=(const Texture3D& other) = delete;
|
||||||
Texture3D& operator=(Texture3D&& other) noexcept;
|
Texture3D& operator=(Texture3D&& other) noexcept;
|
||||||
|
|
||||||
TextureType GetTextureType() const override;
|
[[nodiscard]] TextureType GetTextureType() const override;
|
||||||
|
|
||||||
unsigned GetWidth() const override;
|
[[nodiscard]] unsigned GetWidth() const override;
|
||||||
unsigned GetHeight() const override;
|
[[nodiscard]] unsigned GetHeight() const override;
|
||||||
unsigned GetDepth() const override;
|
[[nodiscard]] unsigned GetDepth() const override;
|
||||||
int GetFaceCount() const override;
|
[[nodiscard]] int GetFaceCount() const override;
|
||||||
|
|
||||||
size_t GetSizeOfMipLevel(int mipLevel) const override;
|
[[nodiscard]] size_t GetSizeOfMipLevel(int mipLevel) const override;
|
||||||
uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
|
[[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
|
||||||
|
[[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const override;
|
||||||
|
|
||||||
int GetMipMapCount() const override;
|
[[nodiscard]] int GetMipMapCount() const override;
|
||||||
};
|
};
|
||||||
|
@ -104,7 +104,7 @@ void TextureConverter::SetPixelFunctions(const unsigned inBitCount, const unsign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureConverter::TextureConverter(Texture* inputTexture, const ImageFormat* targetFormat)
|
TextureConverter::TextureConverter(const Texture* inputTexture, const ImageFormat* targetFormat)
|
||||||
: m_input_texture(inputTexture),
|
: m_input_texture(inputTexture),
|
||||||
m_output_texture(nullptr),
|
m_output_texture(nullptr),
|
||||||
m_input_format(inputTexture->GetFormat()),
|
m_input_format(inputTexture->GetFormat()),
|
||||||
@ -117,15 +117,17 @@ void TextureConverter::CreateOutputTexture()
|
|||||||
switch (m_input_texture->GetTextureType())
|
switch (m_input_texture->GetTextureType())
|
||||||
{
|
{
|
||||||
case TextureType::T_2D:
|
case TextureType::T_2D:
|
||||||
m_output_texture = new Texture2D(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->HasMipMaps());
|
m_output_texture =
|
||||||
|
std::make_unique<Texture2D>(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->HasMipMaps());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextureType::T_CUBE:
|
case TextureType::T_CUBE:
|
||||||
m_output_texture = new TextureCube(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->HasMipMaps());
|
m_output_texture =
|
||||||
|
std::make_unique<TextureCube>(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->HasMipMaps());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextureType::T_3D:
|
case TextureType::T_3D:
|
||||||
m_output_texture = new Texture3D(
|
m_output_texture = std::make_unique<Texture3D>(
|
||||||
m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->GetDepth(), m_input_texture->HasMipMaps());
|
m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->GetDepth(), m_input_texture->HasMipMaps());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -202,7 +204,7 @@ void TextureConverter::ConvertUnsignedToUnsigned()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* TextureConverter::Convert()
|
std::unique_ptr<Texture> TextureConverter::Convert()
|
||||||
{
|
{
|
||||||
CreateOutputTexture();
|
CreateOutputTexture();
|
||||||
|
|
||||||
@ -216,5 +218,5 @@ Texture* TextureConverter::Convert()
|
|||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_output_texture;
|
return std::move(m_output_texture);
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,16 @@
|
|||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class TextureConverter
|
class TextureConverter
|
||||||
{
|
{
|
||||||
Texture* m_input_texture;
|
public:
|
||||||
Texture* m_output_texture;
|
TextureConverter(const Texture* inputTexture, const ImageFormat* targetFormat);
|
||||||
const ImageFormat* m_input_format;
|
|
||||||
const ImageFormat* m_output_format;
|
|
||||||
|
|
||||||
std::function<uint64_t(const void* offset, unsigned bitCount)> m_read_pixel_func;
|
std::unique_ptr<Texture> Convert();
|
||||||
std::function<void(void* offset, uint64_t pixel, unsigned bitCount)> m_write_pixel_func;
|
|
||||||
|
|
||||||
|
private:
|
||||||
static constexpr uint64_t Mask1(unsigned length);
|
static constexpr uint64_t Mask1(unsigned length);
|
||||||
void SetPixelFunctions(unsigned inBitCount, unsigned outBitCount);
|
void SetPixelFunctions(unsigned inBitCount, unsigned outBitCount);
|
||||||
|
|
||||||
@ -22,8 +21,11 @@ class TextureConverter
|
|||||||
void ReorderUnsignedToUnsigned() const;
|
void ReorderUnsignedToUnsigned() const;
|
||||||
void ConvertUnsignedToUnsigned();
|
void ConvertUnsignedToUnsigned();
|
||||||
|
|
||||||
public:
|
std::function<uint64_t(const void* offset, unsigned bitCount)> m_read_pixel_func;
|
||||||
TextureConverter(Texture* inputTexture, const ImageFormat* targetFormat);
|
std::function<void(void* offset, uint64_t pixel, unsigned bitCount)> m_write_pixel_func;
|
||||||
|
|
||||||
Texture* Convert();
|
const Texture* m_input_texture;
|
||||||
|
std::unique_ptr<Texture> m_output_texture;
|
||||||
|
const ImageFormat* m_input_format;
|
||||||
|
const ImageFormat* m_output_format;
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,38 @@
|
|||||||
#include "ImageConverter.h"
|
#include "ImageConverter.h"
|
||||||
|
|
||||||
|
#include "Image/Texture.h"
|
||||||
#include "ImageConverterArgs.h"
|
#include "ImageConverterArgs.h"
|
||||||
|
#include "Utils/StringUtils.h"
|
||||||
|
|
||||||
class ImageConverterImpl final : public ImageConverter
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
namespace image_converter
|
||||||
{
|
{
|
||||||
public:
|
constexpr auto EXTENSION_IWI = ".iwi";
|
||||||
|
|
||||||
|
class ImageLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageLoader() = default;
|
||||||
|
virtual ~ImageLoader() = default;
|
||||||
|
ImageLoader(const ImageLoader& other) = default;
|
||||||
|
ImageLoader(ImageLoader&& other) noexcept = default;
|
||||||
|
ImageLoader& operator=(const ImageLoader& other) = default;
|
||||||
|
ImageLoader& operator=(ImageLoader&& other) noexcept = default;
|
||||||
|
|
||||||
|
// virtual Texture*
|
||||||
|
};
|
||||||
|
|
||||||
|
class ImageConverterImpl final : public ImageConverter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageConverterImpl()
|
||||||
|
: m_game_to_convert_to(image_converter::Game::UNKNOWN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool Start(const int argc, const char** argv) override
|
bool Start(const int argc, const char** argv) override
|
||||||
{
|
{
|
||||||
auto shouldContinue = true;
|
auto shouldContinue = true;
|
||||||
@ -14,14 +42,32 @@ public:
|
|||||||
if (!shouldContinue)
|
if (!shouldContinue)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
m_game_to_convert_to = m_args.m_game_to_convert_to;
|
||||||
|
|
||||||
|
for (const auto& file : m_args.m_files_to_convert)
|
||||||
|
Convert(file);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void Convert(const std::string& file)
|
||||||
|
{
|
||||||
|
fs::path filePath(file);
|
||||||
|
auto extension = filePath.extension().string();
|
||||||
|
utils::MakeStringLowerCase(extension);
|
||||||
|
|
||||||
|
if (extension == EXTENSION_IWI)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImageConverterArgs m_args;
|
ImageConverterArgs m_args;
|
||||||
};
|
image_converter::Game m_game_to_convert_to;
|
||||||
|
};
|
||||||
|
} // namespace image_converter
|
||||||
|
|
||||||
std::unique_ptr<ImageConverter> ImageConverter::Create()
|
std::unique_ptr<ImageConverter> ImageConverter::Create()
|
||||||
{
|
{
|
||||||
return std::make_unique<ImageConverterImpl>();
|
return std::make_unique<image_converter::ImageConverterImpl>();
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,59 @@ const CommandLineOption* const OPTION_VERBOSE =
|
|||||||
.WithLongName("verbose")
|
.WithLongName("verbose")
|
||||||
.WithDescription("Outputs a lot more and more detailed messages.")
|
.WithDescription("Outputs a lot more and more detailed messages.")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
constexpr auto CATEGORY_GAME = "Game";
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_GAME_IW3 =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithLongName("iw3")
|
||||||
|
.WithCategory(CATEGORY_GAME)
|
||||||
|
.WithDescription("Converts images for IW3.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_GAME_IW4 =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithLongName("iw4")
|
||||||
|
.WithCategory(CATEGORY_GAME)
|
||||||
|
.WithDescription("Converts images for IW4.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_GAME_IW5 =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithLongName("iw5")
|
||||||
|
.WithCategory(CATEGORY_GAME)
|
||||||
|
.WithDescription("Converts images for IW5.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_GAME_T5 =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithLongName("t5")
|
||||||
|
.WithCategory(CATEGORY_GAME)
|
||||||
|
.WithDescription("Converts images for T5.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_GAME_T6 =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithLongName("t6")
|
||||||
|
.WithCategory(CATEGORY_GAME)
|
||||||
|
.WithDescription("Converts images for T6.")
|
||||||
|
.Build();
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
const CommandLineOption* const COMMAND_LINE_OPTIONS[]{
|
const CommandLineOption* const COMMAND_LINE_OPTIONS[]{
|
||||||
OPTION_HELP,
|
OPTION_HELP,
|
||||||
OPTION_VERSION,
|
OPTION_VERSION,
|
||||||
OPTION_VERBOSE,
|
OPTION_VERBOSE,
|
||||||
|
OPTION_GAME_IW3,
|
||||||
|
OPTION_GAME_IW4,
|
||||||
|
OPTION_GAME_IW5,
|
||||||
|
OPTION_GAME_T5,
|
||||||
|
OPTION_GAME_T6,
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageConverterArgs::ImageConverterArgs()
|
ImageConverterArgs::ImageConverterArgs()
|
||||||
: m_verbose(false),
|
: m_verbose(false),
|
||||||
|
m_game_to_convert_to(image_converter::Game::UNKNOWN),
|
||||||
m_argument_parser(COMMAND_LINE_OPTIONS, std::extent_v<decltype(COMMAND_LINE_OPTIONS)>)
|
m_argument_parser(COMMAND_LINE_OPTIONS, std::extent_v<decltype(COMMAND_LINE_OPTIONS)>)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Utils/Arguments/ArgumentParser.h"
|
#include "Utils/Arguments/ArgumentParser.h"
|
||||||
#include "Utils/ClassUtils.h"
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace image_converter
|
||||||
|
{
|
||||||
|
enum class Game : std::uint8_t
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
IW3,
|
||||||
|
IW4,
|
||||||
|
IW5,
|
||||||
|
T5,
|
||||||
|
T6
|
||||||
|
};
|
||||||
|
} // namespace image_converter
|
||||||
|
|
||||||
class ImageConverterArgs
|
class ImageConverterArgs
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -14,6 +27,7 @@ public:
|
|||||||
|
|
||||||
bool m_verbose;
|
bool m_verbose;
|
||||||
std::vector<std::string> m_files_to_convert;
|
std::vector<std::string> m_files_to_convert;
|
||||||
|
image_converter::Game m_game_to_convert_to;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +79,7 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(zone.get(), context.m_asset_search_path, CreateGdtList(context));
|
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
|
||||||
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -92,11 +92,11 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ObjLoading::LoadAssetForZone(assetLoadingContext.get(), foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjLoading::FinalizeAssetsForZone(assetLoadingContext.get());
|
ObjLoading::FinalizeAssetsForZone(*assetLoadingContext);
|
||||||
|
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(zone.get(), context.m_asset_search_path, CreateGdtList(context));
|
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
|
||||||
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -91,11 +91,11 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ObjLoading::LoadAssetForZone(assetLoadingContext.get(), foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjLoading::FinalizeAssetsForZone(assetLoadingContext.get());
|
ObjLoading::FinalizeAssetsForZone(*assetLoadingContext);
|
||||||
|
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(zone.get(), context.m_asset_search_path, CreateGdtList(context));
|
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
|
||||||
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -91,11 +91,11 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ObjLoading::LoadAssetForZone(assetLoadingContext.get(), foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjLoading::FinalizeAssetsForZone(assetLoadingContext.get());
|
ObjLoading::FinalizeAssetsForZone(*assetLoadingContext);
|
||||||
|
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(zone.get(), context.m_asset_search_path, CreateGdtList(context));
|
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
|
||||||
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -92,11 +92,11 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ObjLoading::LoadAssetForZone(assetLoadingContext.get(), foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjLoading::FinalizeAssetsForZone(assetLoadingContext.get());
|
ObjLoading::FinalizeAssetsForZone(*assetLoadingContext);
|
||||||
|
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(zone.get(), context.m_asset_search_path, CreateGdtList(context));
|
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
|
||||||
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
if (!CreateIgnoredAssetMap(context, assetLoadingContext->m_ignored_asset_map))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -143,11 +143,11 @@ std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext&
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ObjLoading::LoadAssetForZone(assetLoadingContext.get(), foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
if (!ObjLoading::LoadAssetForZone(*assetLoadingContext, foundAssetTypeEntry->second, assetEntry.m_asset_name))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjLoading::FinalizeAssetsForZone(assetLoadingContext.get());
|
ObjLoading::FinalizeAssetsForZone(*assetLoadingContext);
|
||||||
|
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "SearchPath/SearchPathFilesystem.h"
|
#include "SearchPath/SearchPathFilesystem.h"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
@ -14,21 +15,21 @@ LinkerSearchPaths::LinkerSearchPaths(const LinkerArgs& args)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkerSearchPaths::LoadSearchPath(ISearchPath* searchPath) const
|
void LinkerSearchPaths::LoadSearchPath(ISearchPath& searchPath) const
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
{
|
{
|
||||||
printf("Loading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
std::cout << std::format("Loading search path: \"{}\"\n", searchPath.GetPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjLoading::LoadIWDsInSearchPath(searchPath);
|
ObjLoading::LoadIWDsInSearchPath(searchPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkerSearchPaths::UnloadSearchPath(ISearchPath* searchPath) const
|
void LinkerSearchPaths::UnloadSearchPath(ISearchPath& searchPath) const
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
{
|
{
|
||||||
printf("Unloading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
std::cout << std::format("Unloading search path: \"{}\"\n", searchPath.GetPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjLoading::UnloadIWDsInSearchPath(searchPath);
|
ObjLoading::UnloadIWDsInSearchPath(searchPath);
|
||||||
@ -45,15 +46,15 @@ SearchPaths LinkerSearchPaths::GetAssetSearchPathsForProject(const std::string&
|
|||||||
if (!fs::is_directory(absolutePath))
|
if (!fs::is_directory(absolutePath))
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding asset search path (Not found): " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding asset search path (Not found): {}\n", absolutePath.string());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding asset search path: " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding asset search path: {}\n", absolutePath.string());
|
||||||
|
|
||||||
auto searchPath = std::make_unique<SearchPathFilesystem>(searchPathStr);
|
auto searchPath = std::make_unique<SearchPathFilesystem>(searchPathStr);
|
||||||
LoadSearchPath(searchPath.get());
|
LoadSearchPath(*searchPath);
|
||||||
searchPathsForProject.IncludeSearchPath(searchPath.get());
|
searchPathsForProject.IncludeSearchPath(searchPath.get());
|
||||||
m_loaded_project_search_paths.emplace_back(std::move(searchPath));
|
m_loaded_project_search_paths.emplace_back(std::move(searchPath));
|
||||||
}
|
}
|
||||||
@ -79,12 +80,12 @@ SearchPaths LinkerSearchPaths::GetGdtSearchPathsForProject(const std::string& ga
|
|||||||
if (!fs::is_directory(absolutePath))
|
if (!fs::is_directory(absolutePath))
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding gdt search path (Not found): " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding gdt search path (Not found): {}\n", absolutePath.string());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding gdt search path: " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding gdt search path: {}\n", absolutePath.string());
|
||||||
|
|
||||||
searchPathsForProject.CommitSearchPath(std::make_unique<SearchPathFilesystem>(searchPathStr));
|
searchPathsForProject.CommitSearchPath(std::make_unique<SearchPathFilesystem>(searchPathStr));
|
||||||
}
|
}
|
||||||
@ -105,12 +106,12 @@ SearchPaths LinkerSearchPaths::GetSourceSearchPathsForProject(const std::string&
|
|||||||
if (!fs::is_directory(absolutePath))
|
if (!fs::is_directory(absolutePath))
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding source search path (Not found): " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding source search path (Not found): {}\n", absolutePath.string());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding source search path: " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding source search path: {}\n", absolutePath.string());
|
||||||
|
|
||||||
searchPathsForProject.CommitSearchPath(std::make_unique<SearchPathFilesystem>(searchPathStr));
|
searchPathsForProject.CommitSearchPath(std::make_unique<SearchPathFilesystem>(searchPathStr));
|
||||||
}
|
}
|
||||||
@ -129,15 +130,15 @@ bool LinkerSearchPaths::BuildProjectIndependentSearchPaths()
|
|||||||
if (!fs::is_directory(absolutePath))
|
if (!fs::is_directory(absolutePath))
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding asset search path (Not found): " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding asset search path (Not found): {}\n", absolutePath.string());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding asset search path: " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding asset search path: {}\n", absolutePath.string());
|
||||||
|
|
||||||
auto searchPath = std::make_unique<SearchPathFilesystem>(absolutePath.string());
|
auto searchPath = std::make_unique<SearchPathFilesystem>(absolutePath.string());
|
||||||
LoadSearchPath(searchPath.get());
|
LoadSearchPath(*searchPath);
|
||||||
m_asset_search_paths.CommitSearchPath(std::move(searchPath));
|
m_asset_search_paths.CommitSearchPath(std::move(searchPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,12 +149,12 @@ bool LinkerSearchPaths::BuildProjectIndependentSearchPaths()
|
|||||||
if (!fs::is_directory(absolutePath))
|
if (!fs::is_directory(absolutePath))
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Loading gdt search path (Not found): " << absolutePath.string() << "\n";
|
std::cout << std::format("Loading gdt search path (Not found): {}\n", absolutePath.string());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding gdt search path: " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding gdt search path: {}\n", absolutePath.string());
|
||||||
|
|
||||||
m_gdt_search_paths.CommitSearchPath(std::make_unique<SearchPathFilesystem>(absolutePath.string()));
|
m_gdt_search_paths.CommitSearchPath(std::make_unique<SearchPathFilesystem>(absolutePath.string()));
|
||||||
}
|
}
|
||||||
@ -165,12 +166,12 @@ bool LinkerSearchPaths::BuildProjectIndependentSearchPaths()
|
|||||||
if (!fs::is_directory(absolutePath))
|
if (!fs::is_directory(absolutePath))
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Loading source search path (Not found): " << absolutePath.string() << "\n";
|
std::cout << std::format("Loading source search path (Not found): {}\n", absolutePath.string());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Adding source search path: " << absolutePath.string() << "\n";
|
std::cout << std::format("Adding source search path: {}\n", absolutePath.string());
|
||||||
|
|
||||||
m_source_search_paths.CommitSearchPath(std::make_unique<SearchPathFilesystem>(absolutePath.string()));
|
m_source_search_paths.CommitSearchPath(std::make_unique<SearchPathFilesystem>(absolutePath.string()));
|
||||||
}
|
}
|
||||||
@ -182,7 +183,7 @@ void LinkerSearchPaths::UnloadProjectSpecificSearchPaths()
|
|||||||
{
|
{
|
||||||
for (const auto& loadedSearchPath : m_loaded_project_search_paths)
|
for (const auto& loadedSearchPath : m_loaded_project_search_paths)
|
||||||
{
|
{
|
||||||
UnloadSearchPath(loadedSearchPath.get());
|
UnloadSearchPath(*loadedSearchPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_loaded_project_search_paths.clear();
|
m_loaded_project_search_paths.clear();
|
||||||
|
@ -14,13 +14,13 @@ public:
|
|||||||
* \brief Loads a search path.
|
* \brief Loads a search path.
|
||||||
* \param searchPath The search path to load.
|
* \param searchPath The search path to load.
|
||||||
*/
|
*/
|
||||||
void LoadSearchPath(ISearchPath* searchPath) const;
|
void LoadSearchPath(ISearchPath& searchPath) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Unloads a search path.
|
* \brief Unloads a search path.
|
||||||
* \param searchPath The search path to unload.
|
* \param searchPath The search path to unload.
|
||||||
*/
|
*/
|
||||||
void UnloadSearchPath(ISearchPath* searchPath) const;
|
void UnloadSearchPath(ISearchPath& searchPath) const;
|
||||||
|
|
||||||
SearchPaths GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName);
|
SearchPaths GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "AssetLoadingContext.h"
|
#include "AssetLoadingContext.h"
|
||||||
|
|
||||||
AssetLoadingContext::AssetLoadingContext(Zone* zone, ISearchPath* rawSearchPath, std::vector<Gdt*> gdtFiles)
|
AssetLoadingContext::AssetLoadingContext(Zone& zone, ISearchPath& rawSearchPath, std::vector<Gdt*> gdtFiles)
|
||||||
: m_zone(zone),
|
: m_zone(zone),
|
||||||
m_raw_search_path(rawSearchPath),
|
m_raw_search_path(rawSearchPath),
|
||||||
m_gdt_files(std::move(gdtFiles))
|
m_gdt_files(std::move(gdtFiles))
|
||||||
@ -10,7 +10,7 @@ AssetLoadingContext::AssetLoadingContext(Zone* zone, ISearchPath* rawSearchPath,
|
|||||||
|
|
||||||
void AssetLoadingContext::BuildGdtEntryCache()
|
void AssetLoadingContext::BuildGdtEntryCache()
|
||||||
{
|
{
|
||||||
for (auto* gdt : m_gdt_files)
|
for (const auto* gdt : m_gdt_files)
|
||||||
{
|
{
|
||||||
for (const auto& entry : gdt->m_entries)
|
for (const auto& entry : gdt->m_entries)
|
||||||
{
|
{
|
||||||
|
@ -12,18 +12,8 @@
|
|||||||
|
|
||||||
class AssetLoadingContext final : public IGdtQueryable
|
class AssetLoadingContext final : public IGdtQueryable
|
||||||
{
|
{
|
||||||
std::unordered_map<std::string, std::unordered_map<std::string, GdtEntry*>> m_entries_by_gdf_and_by_name;
|
|
||||||
std::unordered_map<std::type_index, std::unique_ptr<IZoneAssetLoaderState>> m_zone_asset_loader_states;
|
|
||||||
|
|
||||||
void BuildGdtEntryCache();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Zone* const m_zone;
|
AssetLoadingContext(Zone& zone, ISearchPath& rawSearchPath, std::vector<Gdt*> gdtFiles);
|
||||||
ISearchPath* const m_raw_search_path;
|
|
||||||
const std::vector<Gdt*> m_gdt_files;
|
|
||||||
std::unordered_map<std::string, asset_type_t> m_ignored_asset_map;
|
|
||||||
|
|
||||||
AssetLoadingContext(Zone* zone, ISearchPath* rawSearchPath, std::vector<Gdt*> gdtFiles);
|
|
||||||
GdtEntry* GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) override;
|
GdtEntry* GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) override;
|
||||||
|
|
||||||
template<typename T> T* GetZoneAssetLoaderState()
|
template<typename T> T* GetZoneAssetLoaderState()
|
||||||
@ -36,9 +26,21 @@ public:
|
|||||||
return dynamic_cast<T*>(foundEntry->second.get());
|
return dynamic_cast<T*>(foundEntry->second.get());
|
||||||
|
|
||||||
auto newState = std::make_unique<T>();
|
auto newState = std::make_unique<T>();
|
||||||
newState->SetZone(m_zone);
|
newState->SetZone(&m_zone);
|
||||||
auto* newStatePtr = newState.get();
|
auto* newStatePtr = newState.get();
|
||||||
m_zone_asset_loader_states.emplace(std::make_pair<std::type_index, std::unique_ptr<IZoneAssetLoaderState>>(typeid(T), std::move(newState)));
|
m_zone_asset_loader_states.emplace(std::make_pair<std::type_index, std::unique_ptr<IZoneAssetLoaderState>>(typeid(T), std::move(newState)));
|
||||||
return newStatePtr;
|
return newStatePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void BuildGdtEntryCache();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Zone& m_zone;
|
||||||
|
ISearchPath& m_raw_search_path;
|
||||||
|
const std::vector<Gdt*> m_gdt_files;
|
||||||
|
std::unordered_map<std::string, asset_type_t> m_ignored_asset_map;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::unordered_map<std::string, GdtEntry*>> m_entries_by_gdf_and_by_name;
|
||||||
|
std::unordered_map<std::type_index, std::unique_ptr<IZoneAssetLoaderState>> m_zone_asset_loader_states;
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
#include <format>
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
AssetLoadingManager::AssetLoadingManager(const std::map<asset_type_t, std::unique_ptr<IAssetLoader>>& assetLoadersByType, AssetLoadingContext& context)
|
AssetLoadingManager::AssetLoadingManager(const std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>>& assetLoadersByType,
|
||||||
|
AssetLoadingContext& context)
|
||||||
: m_asset_loaders_by_type(assetLoadersByType),
|
: m_asset_loaders_by_type(assetLoadersByType),
|
||||||
m_context(context),
|
m_context(context),
|
||||||
m_last_dependency_loaded(nullptr)
|
m_last_dependency_loaded(nullptr)
|
||||||
@ -28,26 +29,26 @@ XAssetInfoGeneric* AssetLoadingManager::AddAssetInternal(std::unique_ptr<XAssetI
|
|||||||
const auto assetType = xAssetInfo->m_type;
|
const auto assetType = xAssetInfo->m_type;
|
||||||
const auto* pAssetName = xAssetInfo->m_name.c_str();
|
const auto* pAssetName = xAssetInfo->m_name.c_str();
|
||||||
|
|
||||||
m_last_dependency_loaded = m_context.m_zone->m_pools->AddAsset(std::move(xAssetInfo));
|
m_last_dependency_loaded = m_context.m_zone.m_pools->AddAsset(std::move(xAssetInfo));
|
||||||
if (m_last_dependency_loaded == nullptr)
|
if (m_last_dependency_loaded == nullptr)
|
||||||
std::cerr << "Failed to add asset of type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\" to pool: \"" << pAssetName << "\"\n";
|
std::cerr << std::format("Failed to add asset of type \"{}\" to pool: \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType), pAssetName);
|
||||||
|
|
||||||
return m_last_dependency_loaded;
|
return m_last_dependency_loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
XAssetInfoGeneric* AssetLoadingManager::AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo)
|
XAssetInfoGeneric* AssetLoadingManager::AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo)
|
||||||
{
|
{
|
||||||
xAssetInfo->m_zone = m_context.m_zone;
|
xAssetInfo->m_zone = &m_context.m_zone;
|
||||||
return AddAssetInternal(std::move(xAssetInfo));
|
return AddAssetInternal(std::move(xAssetInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
XAssetInfoGeneric* AssetLoadingManager::LoadIgnoredDependency(const asset_type_t assetType, const std::string& assetName, IAssetLoader* loader)
|
XAssetInfoGeneric* AssetLoadingManager::LoadIgnoredDependency(const asset_type_t assetType, const std::string& assetName, IAssetLoader* loader)
|
||||||
{
|
{
|
||||||
auto* alreadyLoadedAsset = m_context.m_zone->m_pools->GetAssetOrAssetReference(assetType, assetName);
|
auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName);
|
||||||
if (alreadyLoadedAsset)
|
if (alreadyLoadedAsset)
|
||||||
return alreadyLoadedAsset;
|
return alreadyLoadedAsset;
|
||||||
|
|
||||||
auto* linkAsset = loader->CreateEmptyAsset(assetName, m_context.m_zone->GetMemory());
|
auto* linkAsset = loader->CreateEmptyAsset(assetName, m_context.m_zone.GetMemory());
|
||||||
if (linkAsset)
|
if (linkAsset)
|
||||||
{
|
{
|
||||||
AddAsset(std::make_unique<XAssetInfoGeneric>(assetType, assetName, linkAsset));
|
AddAsset(std::make_unique<XAssetInfoGeneric>(assetType, assetName, linkAsset));
|
||||||
@ -65,21 +66,21 @@ XAssetInfoGeneric* AssetLoadingManager::LoadIgnoredDependency(const asset_type_t
|
|||||||
return lastDependency;
|
return lastDependency;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << "Failed to create empty asset \"" << assetName << "\" for type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\"\n";
|
std::cerr << std::format("Failed to create empty asset \"{}\" for type \"{}\"\n", assetName, m_context.m_zone.m_pools->GetAssetTypeName(assetType));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t assetType, const std::string& assetName, const IAssetLoader* loader)
|
XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t assetType, const std::string& assetName, const IAssetLoader* loader)
|
||||||
{
|
{
|
||||||
if (loader->CanLoadFromGdt() && !m_context.m_gdt_files.empty()
|
if (loader->CanLoadFromGdt() && !m_context.m_gdt_files.empty()
|
||||||
&& loader->LoadFromGdt(assetName, &m_context, m_context.m_zone->GetMemory(), this, m_context.m_zone))
|
&& loader->LoadFromGdt(assetName, &m_context, m_context.m_zone.GetMemory(), this, &m_context.m_zone))
|
||||||
{
|
{
|
||||||
auto* lastDependency = m_last_dependency_loaded;
|
auto* lastDependency = m_last_dependency_loaded;
|
||||||
m_last_dependency_loaded = nullptr;
|
m_last_dependency_loaded = nullptr;
|
||||||
return lastDependency;
|
return lastDependency;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loader->CanLoadFromRaw() && loader->LoadFromRaw(assetName, m_context.m_raw_search_path, m_context.m_zone->GetMemory(), this, m_context.m_zone))
|
if (loader->CanLoadFromRaw() && loader->LoadFromRaw(assetName, &m_context.m_raw_search_path, m_context.m_zone.GetMemory(), this, &m_context.m_zone))
|
||||||
{
|
{
|
||||||
auto* lastDependency = m_last_dependency_loaded;
|
auto* lastDependency = m_last_dependency_loaded;
|
||||||
m_last_dependency_loaded = nullptr;
|
m_last_dependency_loaded = nullptr;
|
||||||
@ -110,7 +111,7 @@ XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t a
|
|||||||
// Make sure any used script string is available in the created zone
|
// Make sure any used script string is available in the created zone
|
||||||
// The replacement of the scr_string_t values will be done upon writing
|
// The replacement of the scr_string_t values will be done upon writing
|
||||||
for (const auto scrString : existingAsset->m_used_script_strings)
|
for (const auto scrString : existingAsset->m_used_script_strings)
|
||||||
m_context.m_zone->m_script_strings.AddOrGetScriptString(existingAsset->m_zone->m_script_strings.CValue(scrString));
|
m_context.m_zone.m_script_strings.AddOrGetScriptString(existingAsset->m_zone->m_script_strings.CValue(scrString));
|
||||||
|
|
||||||
AddAssetInternal(std::make_unique<XAssetInfoGeneric>(existingAsset->m_type,
|
AddAssetInternal(std::make_unique<XAssetInfoGeneric>(existingAsset->m_type,
|
||||||
existingAsset->m_name,
|
existingAsset->m_name,
|
||||||
@ -125,13 +126,13 @@ XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t a
|
|||||||
return lastDependency;
|
return lastDependency;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << "Failed to load asset of type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\": \"" << assetName << "\"\n";
|
std::cerr << std::format("Failed to load asset of type \"{}\": \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType), assetName);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
XAssetInfoGeneric* AssetLoadingManager::LoadDependency(const asset_type_t assetType, const std::string& assetName)
|
XAssetInfoGeneric* AssetLoadingManager::LoadDependency(const asset_type_t assetType, const std::string& assetName)
|
||||||
{
|
{
|
||||||
auto* alreadyLoadedAsset = m_context.m_zone->m_pools->GetAssetOrAssetReference(assetType, assetName);
|
auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName);
|
||||||
if (alreadyLoadedAsset)
|
if (alreadyLoadedAsset)
|
||||||
return alreadyLoadedAsset;
|
return alreadyLoadedAsset;
|
||||||
|
|
||||||
@ -149,13 +150,13 @@ XAssetInfoGeneric* AssetLoadingManager::LoadDependency(const asset_type_t assetT
|
|||||||
return LoadAssetDependency(assetType, assetName, loader->second.get());
|
return LoadAssetDependency(assetType, assetName, loader->second.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << "Failed to find loader for asset type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\"\n";
|
std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
IndirectAssetReference AssetLoadingManager::LoadIndirectAssetReference(const asset_type_t assetType, const std::string& assetName)
|
IndirectAssetReference AssetLoadingManager::LoadIndirectAssetReference(const asset_type_t assetType, const std::string& assetName)
|
||||||
{
|
{
|
||||||
const auto* alreadyLoadedAsset = m_context.m_zone->m_pools->GetAssetOrAssetReference(assetType, assetName);
|
const auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName);
|
||||||
if (alreadyLoadedAsset)
|
if (alreadyLoadedAsset)
|
||||||
return IndirectAssetReference(assetType, assetName);
|
return IndirectAssetReference(assetType, assetName);
|
||||||
|
|
||||||
@ -170,6 +171,6 @@ IndirectAssetReference AssetLoadingManager::LoadIndirectAssetReference(const ass
|
|||||||
return IndirectAssetReference(assetType, assetName);
|
return IndirectAssetReference(assetType, assetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << "Failed to find loader for asset type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\"\n";
|
std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType));
|
||||||
return IndirectAssetReference(assetType, assetName);
|
return IndirectAssetReference(assetType, assetName);
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
#include "IAssetLoader.h"
|
#include "IAssetLoader.h"
|
||||||
#include "IAssetLoadingManager.h"
|
#include "IAssetLoadingManager.h"
|
||||||
|
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class AssetLoadingManager final : public IAssetLoadingManager
|
class AssetLoadingManager final : public IAssetLoadingManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AssetLoadingManager(const std::map<asset_type_t, std::unique_ptr<IAssetLoader>>& assetLoadersByType, AssetLoadingContext& context);
|
AssetLoadingManager(const std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>>& assetLoadersByType, AssetLoadingContext& context);
|
||||||
|
|
||||||
bool LoadAssetFromLoader(asset_type_t assetType, const std::string& assetName);
|
bool LoadAssetFromLoader(asset_type_t assetType, const std::string& assetName);
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ private:
|
|||||||
|
|
||||||
XAssetInfoGeneric* AddAssetInternal(std::unique_ptr<XAssetInfoGeneric> xAssetInfo);
|
XAssetInfoGeneric* AddAssetInternal(std::unique_ptr<XAssetInfoGeneric> xAssetInfo);
|
||||||
|
|
||||||
const std::map<asset_type_t, std::unique_ptr<IAssetLoader>>& m_asset_loaders_by_type;
|
const std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>>& m_asset_loaders_by_type;
|
||||||
AssetLoadingContext& m_context;
|
AssetLoadingContext& m_context;
|
||||||
XAssetInfoGeneric* m_last_dependency_loaded;
|
XAssetInfoGeneric* m_last_dependency_loaded;
|
||||||
};
|
};
|
||||||
|
@ -46,7 +46,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FinalizeAssetsForZone(AssetLoadingContext* context) const
|
virtual void FinalizeAssetsForZone(AssetLoadingContext& context) const
|
||||||
{
|
{
|
||||||
// Do nothing by default
|
// Do nothing by default
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,9 @@
|
|||||||
#include "Image/IwiTypes.h"
|
#include "Image/IwiTypes.h"
|
||||||
#include "Pool/GlobalAssetPool.h"
|
#include "Pool/GlobalAssetPool.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace IW3;
|
using namespace IW3;
|
||||||
@ -32,20 +34,9 @@ bool AssetLoaderGfxImage::LoadFromRaw(
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string safeAssetName = assetName;
|
std::string safeAssetName = assetName;
|
||||||
for (auto& c : safeAssetName)
|
std::ranges::replace(safeAssetName, '*', '_');
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '*':
|
|
||||||
c = '_';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
const auto file = searchPath->Open(std::format("images/{}.dds", safeAssetName));
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto file = searchPath->Open("images/" + safeAssetName + ".dds");
|
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -54,7 +45,7 @@ bool AssetLoaderGfxImage::LoadFromRaw(
|
|||||||
|
|
||||||
if (texture == nullptr)
|
if (texture == nullptr)
|
||||||
{
|
{
|
||||||
std::cout << "Failed to load dds file for image asset \"" << assetName << "\"\n";
|
std::cout << std::format("Failed to load dds file for image asset \"{}\"\n", assetName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,13 +4,7 @@
|
|||||||
#include "AssetLoaders/AssetLoaderLocalizeEntry.h"
|
#include "AssetLoaders/AssetLoaderLocalizeEntry.h"
|
||||||
#include "AssetLoaders/AssetLoaderRawFile.h"
|
#include "AssetLoaders/AssetLoaderRawFile.h"
|
||||||
#include "AssetLoading/AssetLoadingManager.h"
|
#include "AssetLoading/AssetLoadingManager.h"
|
||||||
#include "Game/IW3/GameAssetPoolIW3.h"
|
|
||||||
#include "Game/IW3/GameIW3.h"
|
#include "Game/IW3/GameIW3.h"
|
||||||
#include "Image/Dx9TextureLoader.h"
|
|
||||||
#include "Image/IwiLoader.h"
|
|
||||||
#include "Image/IwiTypes.h"
|
|
||||||
#include "Image/Texture.h"
|
|
||||||
#include "ObjContainer/IPak/IPak.h"
|
|
||||||
#include "ObjLoading.h"
|
#include "ObjLoading.h"
|
||||||
|
|
||||||
using namespace IW3;
|
using namespace IW3;
|
||||||
@ -54,129 +48,32 @@ ObjLoader::ObjLoader()
|
|||||||
#undef REGISTER_ASSET_LOADER
|
#undef REGISTER_ASSET_LOADER
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::SupportsZone(Zone* zone) const
|
bool ObjLoader::SupportsZone(const Zone& zone) const
|
||||||
{
|
{
|
||||||
return zone->m_game == &g_GameIW3;
|
return zone.m_game == &g_GameIW3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsMpZone(Zone* zone)
|
bool ObjLoader::IsMpZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
|
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsZmZone(Zone* zone)
|
bool ObjLoader::IsZmZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
|
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const {}
|
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {}
|
||||||
|
|
||||||
void ObjLoader::UnloadContainersOfZone(Zone* zone) const {}
|
void ObjLoader::UnloadContainersOfZone(Zone& zone) const {}
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
|
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName) const
|
||||||
{
|
{
|
||||||
const auto* loadDef = image->texture.loadDef;
|
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
|
||||||
Dx9TextureLoader textureLoader(zone->GetMemory());
|
|
||||||
|
|
||||||
textureLoader.Width(loadDef->dimensions[0]).Height(loadDef->dimensions[1]).Depth(loadDef->dimensions[2]);
|
|
||||||
|
|
||||||
if (loadDef->flags & iwi6::IMG_FLAG_VOLMAP)
|
|
||||||
textureLoader.Type(TextureType::T_3D);
|
|
||||||
else if (loadDef->flags & iwi6::IMG_FLAG_CUBEMAP)
|
|
||||||
textureLoader.Type(TextureType::T_CUBE);
|
|
||||||
else
|
|
||||||
textureLoader.Type(TextureType::T_2D);
|
|
||||||
|
|
||||||
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef->format));
|
|
||||||
textureLoader.HasMipMaps(!(loadDef->flags & iwi6::IMG_FLAG_NOMIPMAPS));
|
|
||||||
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->cardMemory.platform[0] = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
Texture* loadedTexture = nullptr;
|
|
||||||
IwiLoader loader(zone->GetMemory());
|
|
||||||
|
|
||||||
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto filePathImage = searchPath->Open(imageFileName);
|
|
||||||
if (filePathImage.IsOpen())
|
|
||||||
{
|
|
||||||
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->cardMemory.platform[0] = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Could not find data for image \"%s\"\n", image->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* assetPool = dynamic_cast<GameAssetPoolIW3*>(zone->m_pools.get());
|
|
||||||
|
|
||||||
if (assetPool && assetPool->m_image != nullptr)
|
|
||||||
{
|
|
||||||
for (auto* imageEntry : *assetPool->m_image)
|
|
||||||
{
|
|
||||||
auto* image = imageEntry->Asset();
|
|
||||||
|
|
||||||
if (image->cardMemory.platform[0] > 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not load linked assets
|
|
||||||
if (image->name && image->name[0] == ',')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
|
||||||
{
|
|
||||||
LoadImageFromLoadDef(image, zone);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LoadImageFromIwi(image, searchPath, zone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
|
|
||||||
{
|
|
||||||
LoadImageData(searchPath, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, const asset_type_t assetType, const std::string& assetName) const
|
|
||||||
{
|
|
||||||
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
|
|
||||||
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
|
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
|
||||||
{
|
{
|
||||||
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
||||||
loader->FinalizeAssetsForZone(context);
|
loader->FinalizeAssetsForZone(context);
|
||||||
|
@ -1,37 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AssetLoading/IAssetLoader.h"
|
#include "AssetLoading/IAssetLoader.h"
|
||||||
#include "Game/IW3/IW3.h"
|
|
||||||
#include "IObjLoader.h"
|
#include "IObjLoader.h"
|
||||||
#include "SearchPath/ISearchPath.h"
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace IW3
|
namespace IW3
|
||||||
{
|
{
|
||||||
class ObjLoader final : public IObjLoader
|
class ObjLoader final : public IObjLoader
|
||||||
{
|
{
|
||||||
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
||||||
|
|
||||||
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
|
static bool IsMpZone(const Zone& zone);
|
||||||
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
|
static bool IsZmZone(const Zone& zone);
|
||||||
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
|
|
||||||
|
|
||||||
static bool IsMpZone(Zone* zone);
|
|
||||||
static bool IsZmZone(Zone* zone);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjLoader();
|
ObjLoader();
|
||||||
|
|
||||||
bool SupportsZone(Zone* zone) const override;
|
[[nodiscard]] bool SupportsZone(const Zone& zone) const override;
|
||||||
|
|
||||||
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
|
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
|
||||||
void UnloadContainersOfZone(Zone* zone) const override;
|
void UnloadContainersOfZone(Zone& zone) const override;
|
||||||
|
|
||||||
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
|
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
|
||||||
|
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
|
||||||
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
|
|
||||||
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
|
|
||||||
};
|
};
|
||||||
} // namespace IW3
|
} // namespace IW3
|
||||||
|
@ -820,10 +820,10 @@ namespace IW4
|
|||||||
m_material->techniqueSet = techset->Asset();
|
m_material->techniqueSet = techset->Asset();
|
||||||
|
|
||||||
auto* loadingContext = m_manager->GetAssetLoadingContext();
|
auto* loadingContext = m_manager->GetAssetLoadingContext();
|
||||||
auto* searchPath = loadingContext->m_raw_search_path;
|
auto& searchPath = loadingContext->m_raw_search_path;
|
||||||
auto* definitionCache = loadingContext->GetZoneAssetLoaderState<techset::TechsetDefinitionCache>();
|
auto* definitionCache = loadingContext->GetZoneAssetLoaderState<techset::TechsetDefinitionCache>();
|
||||||
|
|
||||||
const auto* techsetDefinition = AssetLoaderTechniqueSet::LoadTechsetDefinition(techsetName, searchPath, definitionCache);
|
const auto* techsetDefinition = AssetLoaderTechniqueSet::LoadTechsetDefinition(techsetName, &searchPath, definitionCache);
|
||||||
if (techsetDefinition == nullptr)
|
if (techsetDefinition == nullptr)
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
@ -1375,7 +1375,7 @@ bool AssetLoaderMaterial::LoadFromGdt(
|
|||||||
if (!entry)
|
if (!entry)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MaterialGdtLoader loader(*entry, memory, manager->GetAssetLoadingContext()->m_raw_search_path, manager);
|
MaterialGdtLoader loader(*entry, memory, &manager->GetAssetLoadingContext()->m_raw_search_path, manager);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -227,7 +227,7 @@ bool AssetLoaderMenuList::LoadFromRaw(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext* context) const
|
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext& context) const
|
||||||
{
|
{
|
||||||
context->GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
|
context.GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,6 @@ namespace IW4
|
|||||||
_NODISCARD bool CanLoadFromRaw() const override;
|
_NODISCARD bool CanLoadFromRaw() const override;
|
||||||
bool
|
bool
|
||||||
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
||||||
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
|
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
|
||||||
};
|
};
|
||||||
} // namespace IW4
|
} // namespace IW4
|
||||||
|
@ -37,14 +37,9 @@
|
|||||||
#include "AssetLoaders/AssetLoaderXModel.h"
|
#include "AssetLoaders/AssetLoaderXModel.h"
|
||||||
#include "AssetLoaders/AssetLoaderXModelSurfs.h"
|
#include "AssetLoaders/AssetLoaderXModelSurfs.h"
|
||||||
#include "AssetLoading/AssetLoadingManager.h"
|
#include "AssetLoading/AssetLoadingManager.h"
|
||||||
#include "Game/IW4/GameAssetPoolIW4.h"
|
|
||||||
#include "Game/IW4/GameIW4.h"
|
#include "Game/IW4/GameIW4.h"
|
||||||
#include "Image/Dx9TextureLoader.h"
|
|
||||||
#include "Image/IwiLoader.h"
|
#include "Image/IwiLoader.h"
|
||||||
#include "Image/IwiTypes.h"
|
|
||||||
#include "Image/Texture.h"
|
|
||||||
#include "ObjContainer/IPak/IPak.h"
|
#include "ObjContainer/IPak/IPak.h"
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
@ -97,129 +92,32 @@ ObjLoader::ObjLoader()
|
|||||||
#undef REGISTER_ASSET_LOADER
|
#undef REGISTER_ASSET_LOADER
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::SupportsZone(Zone* zone) const
|
bool ObjLoader::SupportsZone(const Zone& zone) const
|
||||||
{
|
{
|
||||||
return zone->m_game == &g_GameIW4;
|
return zone.m_game == &g_GameIW4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsMpZone(Zone* zone)
|
bool ObjLoader::IsMpZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
|
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsZmZone(Zone* zone)
|
bool ObjLoader::IsZmZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
|
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const {}
|
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {}
|
||||||
|
|
||||||
void ObjLoader::UnloadContainersOfZone(Zone* zone) const {}
|
void ObjLoader::UnloadContainersOfZone(Zone& zone) const {}
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
|
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const
|
||||||
{
|
{
|
||||||
const auto* loadDef = image->texture.loadDef;
|
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
|
||||||
Dx9TextureLoader textureLoader(zone->GetMemory());
|
|
||||||
|
|
||||||
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
|
|
||||||
|
|
||||||
if ((loadDef->flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_3D)
|
|
||||||
textureLoader.Type(TextureType::T_3D);
|
|
||||||
else if ((loadDef->flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_CUBE)
|
|
||||||
textureLoader.Type(TextureType::T_CUBE);
|
|
||||||
else
|
|
||||||
textureLoader.Type(TextureType::T_2D);
|
|
||||||
|
|
||||||
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef->format));
|
|
||||||
textureLoader.HasMipMaps(!(loadDef->flags & iwi8::IMG_FLAG_NOMIPMAPS));
|
|
||||||
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->cardMemory.platform[0] = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
Texture* loadedTexture = nullptr;
|
|
||||||
IwiLoader loader(zone->GetMemory());
|
|
||||||
|
|
||||||
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto filePathImage = searchPath->Open(imageFileName);
|
|
||||||
if (filePathImage.IsOpen())
|
|
||||||
{
|
|
||||||
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->cardMemory.platform[0] = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Could not find data for image \"%s\"\n", image->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* assetPool = dynamic_cast<GameAssetPoolIW4*>(zone->m_pools.get());
|
|
||||||
|
|
||||||
if (assetPool && assetPool->m_image != nullptr)
|
|
||||||
{
|
|
||||||
for (auto* imageEntry : *assetPool->m_image)
|
|
||||||
{
|
|
||||||
auto* image = imageEntry->Asset();
|
|
||||||
|
|
||||||
if (image->cardMemory.platform[0] > 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not load linked assets
|
|
||||||
if (image->name && image->name[0] == ',')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
|
||||||
{
|
|
||||||
LoadImageFromLoadDef(image, zone);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LoadImageFromIwi(image, searchPath, zone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
|
|
||||||
{
|
|
||||||
LoadImageData(searchPath, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const
|
|
||||||
{
|
|
||||||
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
|
|
||||||
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
|
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
|
||||||
{
|
{
|
||||||
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
||||||
loader->FinalizeAssetsForZone(context);
|
loader->FinalizeAssetsForZone(context);
|
||||||
|
@ -1,37 +1,31 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AssetLoading/IAssetLoader.h"
|
#include "AssetLoading/IAssetLoader.h"
|
||||||
#include "Game/IW4/IW4.h"
|
|
||||||
#include "IObjLoader.h"
|
#include "IObjLoader.h"
|
||||||
#include "SearchPath/ISearchPath.h"
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace IW4
|
namespace IW4
|
||||||
{
|
{
|
||||||
class ObjLoader final : public IObjLoader
|
class ObjLoader final : public IObjLoader
|
||||||
{
|
{
|
||||||
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
|
||||||
|
|
||||||
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
|
|
||||||
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
|
|
||||||
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
|
|
||||||
|
|
||||||
static bool IsMpZone(Zone* zone);
|
|
||||||
static bool IsZmZone(Zone* zone);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjLoader();
|
ObjLoader();
|
||||||
|
|
||||||
bool SupportsZone(Zone* zone) const override;
|
[[nodiscard]] bool SupportsZone(const Zone& zone) const override;
|
||||||
|
|
||||||
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
|
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
|
||||||
void UnloadContainersOfZone(Zone* zone) const override;
|
void UnloadContainersOfZone(Zone& zone) const override;
|
||||||
|
|
||||||
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
|
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
|
||||||
|
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
|
||||||
|
|
||||||
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
|
private:
|
||||||
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
|
static bool IsMpZone(const Zone& zone);
|
||||||
|
static bool IsZmZone(const Zone& zone);
|
||||||
|
|
||||||
|
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
||||||
};
|
};
|
||||||
} // namespace IW4
|
} // namespace IW4
|
||||||
|
@ -35,10 +35,8 @@ bool AssetLoaderGfxImage::LoadFromRaw(
|
|||||||
const auto fileData = std::make_unique<char[]>(fileSize);
|
const auto fileData = std::make_unique<char[]>(fileSize);
|
||||||
file.m_stream->read(fileData.get(), fileSize);
|
file.m_stream->read(fileData.get(), fileSize);
|
||||||
|
|
||||||
MemoryManager tempMemory;
|
|
||||||
IwiLoader iwiLoader(&tempMemory);
|
|
||||||
std::istringstream ss(std::string(fileData.get(), fileSize));
|
std::istringstream ss(std::string(fileData.get(), fileSize));
|
||||||
const auto texture = iwiLoader.LoadIwi(ss);
|
const auto texture = iwi::LoadIwi(ss);
|
||||||
if (!texture)
|
if (!texture)
|
||||||
{
|
{
|
||||||
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
|
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
|
||||||
|
@ -227,7 +227,7 @@ bool AssetLoaderMenuList::LoadFromRaw(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext* context) const
|
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext& context) const
|
||||||
{
|
{
|
||||||
context->GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
|
context.GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,6 @@ namespace IW5
|
|||||||
_NODISCARD bool CanLoadFromRaw() const override;
|
_NODISCARD bool CanLoadFromRaw() const override;
|
||||||
bool
|
bool
|
||||||
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
||||||
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
|
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
|
||||||
};
|
};
|
||||||
} // namespace IW5
|
} // namespace IW5
|
||||||
|
@ -41,14 +41,9 @@
|
|||||||
#include "AssetLoaders/AssetLoaderXModel.h"
|
#include "AssetLoaders/AssetLoaderXModel.h"
|
||||||
#include "AssetLoaders/AssetLoaderXModelSurfs.h"
|
#include "AssetLoaders/AssetLoaderXModelSurfs.h"
|
||||||
#include "AssetLoading/AssetLoadingManager.h"
|
#include "AssetLoading/AssetLoadingManager.h"
|
||||||
#include "Game/IW5/GameAssetPoolIW5.h"
|
|
||||||
#include "Game/IW5/GameIW5.h"
|
#include "Game/IW5/GameIW5.h"
|
||||||
#include "Image/Dx9TextureLoader.h"
|
|
||||||
#include "Image/IwiLoader.h"
|
#include "Image/IwiLoader.h"
|
||||||
#include "Image/IwiTypes.h"
|
|
||||||
#include "Image/Texture.h"
|
|
||||||
#include "ObjContainer/IPak/IPak.h"
|
#include "ObjContainer/IPak/IPak.h"
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace IW5;
|
using namespace IW5;
|
||||||
|
|
||||||
@ -104,129 +99,32 @@ ObjLoader::ObjLoader()
|
|||||||
#undef REGISTER_ASSET_LOADER
|
#undef REGISTER_ASSET_LOADER
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::SupportsZone(Zone* zone) const
|
bool ObjLoader::SupportsZone(const Zone& zone) const
|
||||||
{
|
{
|
||||||
return zone->m_game == &g_GameIW5;
|
return zone.m_game == &g_GameIW5;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsMpZone(Zone* zone)
|
bool ObjLoader::IsMpZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
|
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsZmZone(Zone* zone)
|
bool ObjLoader::IsZmZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
|
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const {}
|
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {}
|
||||||
|
|
||||||
void ObjLoader::UnloadContainersOfZone(Zone* zone) const {}
|
void ObjLoader::UnloadContainersOfZone(Zone& zone) const {}
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
|
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName) const
|
||||||
{
|
{
|
||||||
const auto* loadDef = image->texture.loadDef;
|
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
|
||||||
Dx9TextureLoader textureLoader(zone->GetMemory());
|
|
||||||
|
|
||||||
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
|
|
||||||
|
|
||||||
if ((loadDef->flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_3D)
|
|
||||||
textureLoader.Type(TextureType::T_3D);
|
|
||||||
else if ((loadDef->flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_CUBE)
|
|
||||||
textureLoader.Type(TextureType::T_CUBE);
|
|
||||||
else
|
|
||||||
textureLoader.Type(TextureType::T_2D);
|
|
||||||
|
|
||||||
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef->format));
|
|
||||||
textureLoader.HasMipMaps(!(loadDef->flags & iwi8::IMG_FLAG_NOMIPMAPS));
|
|
||||||
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->cardMemory.platform[0] = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
Texture* loadedTexture = nullptr;
|
|
||||||
IwiLoader loader(zone->GetMemory());
|
|
||||||
|
|
||||||
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto filePathImage = searchPath->Open(imageFileName);
|
|
||||||
if (filePathImage.IsOpen())
|
|
||||||
{
|
|
||||||
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->cardMemory.platform[0] = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Could not find data for image \"%s\"\n", image->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* assetPool = dynamic_cast<GameAssetPoolIW5*>(zone->m_pools.get());
|
|
||||||
|
|
||||||
if (assetPool && assetPool->m_image != nullptr)
|
|
||||||
{
|
|
||||||
for (auto* imageEntry : *assetPool->m_image)
|
|
||||||
{
|
|
||||||
auto* image = imageEntry->Asset();
|
|
||||||
|
|
||||||
if (image->cardMemory.platform[0] > 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not load linked assets
|
|
||||||
if (image->name && image->name[0] == ',')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
|
||||||
{
|
|
||||||
LoadImageFromLoadDef(image, zone);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LoadImageFromIwi(image, searchPath, zone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
|
|
||||||
{
|
|
||||||
LoadImageData(searchPath, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const
|
|
||||||
{
|
|
||||||
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
|
|
||||||
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
|
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
|
||||||
{
|
{
|
||||||
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
||||||
loader->FinalizeAssetsForZone(context);
|
loader->FinalizeAssetsForZone(context);
|
||||||
|
@ -1,37 +1,31 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AssetLoading/IAssetLoader.h"
|
#include "AssetLoading/IAssetLoader.h"
|
||||||
#include "Game/IW5/IW5.h"
|
|
||||||
#include "IObjLoader.h"
|
#include "IObjLoader.h"
|
||||||
#include "SearchPath/ISearchPath.h"
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace IW5
|
namespace IW5
|
||||||
{
|
{
|
||||||
class ObjLoader final : public IObjLoader
|
class ObjLoader final : public IObjLoader
|
||||||
{
|
{
|
||||||
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
|
||||||
|
|
||||||
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
|
|
||||||
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
|
|
||||||
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
|
|
||||||
|
|
||||||
static bool IsMpZone(Zone* zone);
|
|
||||||
static bool IsZmZone(Zone* zone);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjLoader();
|
ObjLoader();
|
||||||
|
|
||||||
bool SupportsZone(Zone* zone) const override;
|
[[nodiscard]] bool SupportsZone(const Zone& zone) const override;
|
||||||
|
|
||||||
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
|
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
|
||||||
void UnloadContainersOfZone(Zone* zone) const override;
|
void UnloadContainersOfZone(Zone& zone) const override;
|
||||||
|
|
||||||
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
|
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
|
||||||
|
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
|
||||||
|
|
||||||
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
|
private:
|
||||||
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
|
static bool IsMpZone(const Zone& zone);
|
||||||
|
static bool IsZmZone(const Zone& zone);
|
||||||
|
|
||||||
|
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
||||||
};
|
};
|
||||||
} // namespace IW5
|
} // namespace IW5
|
||||||
|
@ -5,14 +5,9 @@
|
|||||||
#include "AssetLoaders/AssetLoaderStringTable.h"
|
#include "AssetLoaders/AssetLoaderStringTable.h"
|
||||||
#include "AssetLoaders/AssetLoaderXModel.h"
|
#include "AssetLoaders/AssetLoaderXModel.h"
|
||||||
#include "AssetLoading/AssetLoadingManager.h"
|
#include "AssetLoading/AssetLoadingManager.h"
|
||||||
#include "Game/T5/GameAssetPoolT5.h"
|
|
||||||
#include "Game/T5/GameT5.h"
|
#include "Game/T5/GameT5.h"
|
||||||
#include "Image/Dx9TextureLoader.h"
|
|
||||||
#include "Image/IwiLoader.h"
|
#include "Image/IwiLoader.h"
|
||||||
#include "Image/IwiTypes.h"
|
|
||||||
#include "Image/Texture.h"
|
|
||||||
#include "ObjContainer/IPak/IPak.h"
|
#include "ObjContainer/IPak/IPak.h"
|
||||||
#include "ObjLoading.h"
|
|
||||||
|
|
||||||
using namespace T5;
|
using namespace T5;
|
||||||
|
|
||||||
@ -61,129 +56,32 @@ ObjLoader::ObjLoader()
|
|||||||
#undef REGISTER_ASSET_LOADER
|
#undef REGISTER_ASSET_LOADER
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::SupportsZone(Zone* zone) const
|
bool ObjLoader::SupportsZone(const Zone& zone) const
|
||||||
{
|
{
|
||||||
return zone->m_game == &g_GameT5;
|
return zone.m_game == &g_GameT5;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsMpZone(Zone* zone)
|
bool ObjLoader::IsMpZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
|
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsZmZone(Zone* zone)
|
bool ObjLoader::IsZmZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
|
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const {}
|
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {}
|
||||||
|
|
||||||
void ObjLoader::UnloadContainersOfZone(Zone* zone) const {}
|
void ObjLoader::UnloadContainersOfZone(Zone& zone) const {}
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
|
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const
|
||||||
{
|
{
|
||||||
const auto* loadDef = image->texture.loadDef;
|
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
|
||||||
Dx9TextureLoader textureLoader(zone->GetMemory());
|
|
||||||
|
|
||||||
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
|
|
||||||
|
|
||||||
if (loadDef->flags & iwi13::IMG_FLAG_VOLMAP)
|
|
||||||
textureLoader.Type(TextureType::T_3D);
|
|
||||||
else if (loadDef->flags & iwi13::IMG_FLAG_CUBEMAP)
|
|
||||||
textureLoader.Type(TextureType::T_CUBE);
|
|
||||||
else
|
|
||||||
textureLoader.Type(TextureType::T_2D);
|
|
||||||
|
|
||||||
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef->format));
|
|
||||||
textureLoader.HasMipMaps(!(loadDef->flags & iwi13::IMG_FLAG_NOMIPMAPS));
|
|
||||||
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->loadedSize = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->loadedSize += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
Texture* loadedTexture = nullptr;
|
|
||||||
IwiLoader loader(zone->GetMemory());
|
|
||||||
|
|
||||||
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto filePathImage = searchPath->Open(imageFileName);
|
|
||||||
if (filePathImage.IsOpen())
|
|
||||||
{
|
|
||||||
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->loadedSize = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->loadedSize += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Could not find data for image \"%s\"\n", image->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* assetPool = dynamic_cast<GameAssetPoolT5*>(zone->m_pools.get());
|
|
||||||
|
|
||||||
if (assetPool && assetPool->m_image != nullptr)
|
|
||||||
{
|
|
||||||
for (auto* imageEntry : *assetPool->m_image)
|
|
||||||
{
|
|
||||||
auto* image = imageEntry->Asset();
|
|
||||||
|
|
||||||
if (image->loadedSize > 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not load linked assets
|
|
||||||
if (image->name && image->name[0] == ',')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
|
||||||
{
|
|
||||||
LoadImageFromLoadDef(image, zone);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LoadImageFromIwi(image, searchPath, zone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
|
|
||||||
{
|
|
||||||
LoadImageData(searchPath, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const
|
|
||||||
{
|
|
||||||
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
|
|
||||||
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
|
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
|
||||||
{
|
{
|
||||||
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
||||||
loader->FinalizeAssetsForZone(context);
|
loader->FinalizeAssetsForZone(context);
|
||||||
|
@ -1,37 +1,31 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AssetLoading/IAssetLoader.h"
|
#include "AssetLoading/IAssetLoader.h"
|
||||||
#include "Game/T5/T5.h"
|
|
||||||
#include "IObjLoader.h"
|
#include "IObjLoader.h"
|
||||||
#include "SearchPath/ISearchPath.h"
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace T5
|
namespace T5
|
||||||
{
|
{
|
||||||
class ObjLoader final : public IObjLoader
|
class ObjLoader final : public IObjLoader
|
||||||
{
|
{
|
||||||
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
|
||||||
|
|
||||||
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
|
|
||||||
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
|
|
||||||
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
|
|
||||||
|
|
||||||
static bool IsMpZone(Zone* zone);
|
|
||||||
static bool IsZmZone(Zone* zone);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjLoader();
|
ObjLoader();
|
||||||
|
|
||||||
bool SupportsZone(Zone* zone) const override;
|
bool SupportsZone(const Zone& zone) const override;
|
||||||
|
|
||||||
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
|
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
|
||||||
void UnloadContainersOfZone(Zone* zone) const override;
|
void UnloadContainersOfZone(Zone& zone) const override;
|
||||||
|
|
||||||
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
|
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
|
||||||
|
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
|
||||||
|
|
||||||
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
|
private:
|
||||||
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
|
static bool IsMpZone(const Zone& zone);
|
||||||
|
static bool IsZmZone(const Zone& zone);
|
||||||
|
|
||||||
|
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
||||||
};
|
};
|
||||||
} // namespace T5
|
} // namespace T5
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "Pool/GlobalAssetPool.h"
|
#include "Pool/GlobalAssetPool.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
@ -27,7 +28,7 @@ bool AssetLoaderGfxImage::CanLoadFromRaw() const
|
|||||||
bool AssetLoaderGfxImage::LoadFromRaw(
|
bool AssetLoaderGfxImage::LoadFromRaw(
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
||||||
{
|
{
|
||||||
const auto fileName = "images/" + assetName + ".iwi";
|
const auto fileName = std::format("images/{}.iwi", assetName);
|
||||||
const auto file = searchPath->Open(fileName);
|
const auto file = searchPath->Open(fileName);
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
return false;
|
return false;
|
||||||
@ -37,13 +38,11 @@ bool AssetLoaderGfxImage::LoadFromRaw(
|
|||||||
file.m_stream->read(fileData.get(), fileSize);
|
file.m_stream->read(fileData.get(), fileSize);
|
||||||
const auto dataHash = static_cast<unsigned>(crc32(0u, reinterpret_cast<const Bytef*>(fileData.get()), fileSize));
|
const auto dataHash = static_cast<unsigned>(crc32(0u, reinterpret_cast<const Bytef*>(fileData.get()), fileSize));
|
||||||
|
|
||||||
MemoryManager tempMemory;
|
|
||||||
IwiLoader iwiLoader(&tempMemory);
|
|
||||||
std::istringstream ss(std::string(fileData.get(), fileSize));
|
std::istringstream ss(std::string(fileData.get(), fileSize));
|
||||||
const auto texture = iwiLoader.LoadIwi(ss);
|
const auto texture = iwi::LoadIwi(ss);
|
||||||
if (!texture)
|
if (!texture)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to load texture from: " << fileName << "\n";
|
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,12 +58,12 @@
|
|||||||
#include "ObjContainer/IPak/IPak.h"
|
#include "ObjContainer/IPak/IPak.h"
|
||||||
#include "ObjLoading.h"
|
#include "ObjLoading.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <format>
|
||||||
|
|
||||||
namespace T6
|
namespace T6
|
||||||
{
|
{
|
||||||
const int ObjLoader::IPAK_READ_HASH = Common::Com_HashKey("ipak_read", 64);
|
constexpr auto IPAK_READ_HASH = Common::Com_HashKey("ipak_read", 64);
|
||||||
const int ObjLoader::GLOBAL_HASH = Common::Com_HashKey("GLOBAL", 64);
|
constexpr auto GLOBAL_HASH = Common::Com_HashKey("GLOBAL", 64);
|
||||||
|
|
||||||
ObjLoader::ObjLoader()
|
ObjLoader::ObjLoader()
|
||||||
{
|
{
|
||||||
@ -125,37 +125,37 @@ namespace T6
|
|||||||
#undef REGISTER_ASSET_LOADER
|
#undef REGISTER_ASSET_LOADER
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::SupportsZone(Zone* zone) const
|
bool ObjLoader::SupportsZone(const Zone& zone) const
|
||||||
{
|
{
|
||||||
return zone->m_game == &g_GameT6;
|
return zone.m_game == &g_GameT6;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::VerifySoundBankChecksum(const SoundBank* soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank)
|
bool ObjLoader::VerifySoundBankChecksum(const SoundBank& soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank)
|
||||||
{
|
{
|
||||||
SoundAssetBankChecksum checksum{};
|
SoundAssetBankChecksum checksum{};
|
||||||
static_assert(sizeof(SoundAssetBankChecksum::checksumBytes) == sizeof(SndRuntimeAssetBank::linkTimeChecksum));
|
static_assert(sizeof(SoundAssetBankChecksum::checksumBytes) == sizeof(SndRuntimeAssetBank::linkTimeChecksum));
|
||||||
for (auto i = 0u; i < sizeof(SoundAssetBankChecksum::checksumBytes); i++)
|
for (auto i = 0u; i < sizeof(SoundAssetBankChecksum::checksumBytes); i++)
|
||||||
checksum.checksumBytes[i] = sndRuntimeAssetBank.linkTimeChecksum[i];
|
checksum.checksumBytes[i] = sndRuntimeAssetBank.linkTimeChecksum[i];
|
||||||
|
|
||||||
return soundBank->VerifyChecksum(checksum);
|
return soundBank.VerifyChecksum(checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundBank* ObjLoader::LoadSoundBankForZone(ISearchPath* searchPath, const std::string& soundBankFileName, Zone* zone)
|
SoundBank* ObjLoader::LoadSoundBankForZone(ISearchPath& searchPath, const std::string& soundBankFileName, Zone& zone)
|
||||||
{
|
{
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
std::cout << "Trying to load sound bank '" << soundBankFileName << "' for zone '" << zone->m_name << "'\n";
|
std::cout << std::format("Trying to load sound bank '{}' for zone '{}'\n", soundBankFileName, zone.m_name);
|
||||||
|
|
||||||
auto* existingSoundBank = SoundBank::Repository.GetContainerByName(soundBankFileName);
|
auto* existingSoundBank = SoundBank::Repository.GetContainerByName(soundBankFileName);
|
||||||
if (existingSoundBank != nullptr)
|
if (existingSoundBank != nullptr)
|
||||||
{
|
{
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
std::cout << "Referencing loaded sound bank '" << soundBankFileName << "'.\n";
|
std::cout << std::format("Referencing loaded sound bank '{}'.\n", soundBankFileName);
|
||||||
|
|
||||||
SoundBank::Repository.AddContainerReference(existingSoundBank, zone);
|
SoundBank::Repository.AddContainerReference(existingSoundBank, &zone);
|
||||||
return existingSoundBank;
|
return existingSoundBank;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file = searchPath->Open(soundBankFileName);
|
auto file = searchPath.Open(soundBankFileName);
|
||||||
if (file.IsOpen())
|
if (file.IsOpen())
|
||||||
{
|
{
|
||||||
auto sndBank = std::make_unique<SoundBank>(soundBankFileName, std::move(file.m_stream), file.m_length);
|
auto sndBank = std::make_unique<SoundBank>(soundBankFileName, std::move(file.m_stream), file.m_length);
|
||||||
@ -163,26 +163,26 @@ namespace T6
|
|||||||
|
|
||||||
if (!sndBank->Initialize())
|
if (!sndBank->Initialize())
|
||||||
{
|
{
|
||||||
std::cout << "Failed to load sound bank '" << soundBankFileName << "'\n";
|
std::cerr << std::format("Failed to load sound bank '{}'\n", soundBankFileName);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundBank::Repository.AddContainer(std::move(sndBank), zone);
|
SoundBank::Repository.AddContainer(std::move(sndBank), &zone);
|
||||||
|
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
std::cout << "Found and loaded sound bank '" << soundBankFileName << "'\n";
|
std::cout << std::format("Found and loaded sound bank '{}'\n", soundBankFileName);
|
||||||
|
|
||||||
return sndBankPtr;
|
return sndBankPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Failed to load sound bank '" << soundBankFileName << "'\n";
|
std::cerr << std::format("Failed to load sound bank '{}'\n", soundBankFileName);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::LoadSoundBankFromLinkedInfo(ISearchPath* searchPath,
|
void ObjLoader::LoadSoundBankFromLinkedInfo(ISearchPath& searchPath,
|
||||||
const std::string& soundBankFileName,
|
const std::string& soundBankFileName,
|
||||||
const SndRuntimeAssetBank* sndBankLinkedInfo,
|
const SndRuntimeAssetBank& sndBankLinkedInfo,
|
||||||
Zone* zone,
|
Zone& zone,
|
||||||
std::set<std::string>& loadedBanksForZone,
|
std::set<std::string>& loadedBanksForZone,
|
||||||
std::stack<std::string>& dependenciesToLoad)
|
std::stack<std::string>& dependenciesToLoad)
|
||||||
{
|
{
|
||||||
@ -192,10 +192,9 @@ namespace T6
|
|||||||
|
|
||||||
if (soundBank)
|
if (soundBank)
|
||||||
{
|
{
|
||||||
if (!VerifySoundBankChecksum(soundBank, *sndBankLinkedInfo))
|
if (!VerifySoundBankChecksum(*soundBank, sndBankLinkedInfo))
|
||||||
{
|
std::cout << std::format("Checksum of sound bank does not match link time checksum for '{}'\n", soundBankFileName);
|
||||||
std::cout << "Checksum of sound bank does not match link time checksum for '" << soundBankFileName << "'\n";
|
|
||||||
}
|
|
||||||
loadedBanksForZone.emplace(soundBankFileName);
|
loadedBanksForZone.emplace(soundBankFileName);
|
||||||
|
|
||||||
for (const auto& dependency : soundBank->GetDependencies())
|
for (const auto& dependency : soundBank->GetDependencies())
|
||||||
@ -206,20 +205,20 @@ namespace T6
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::LoadSoundBanksFromAsset(ISearchPath* searchPath, const SndBank* sndBank, Zone* zone, std::set<std::string>& loadedBanksForZone)
|
void ObjLoader::LoadSoundBanksFromAsset(ISearchPath& searchPath, const SndBank& sndBank, Zone& zone, std::set<std::string>& loadedBanksForZone)
|
||||||
{
|
{
|
||||||
std::stack<std::string> dependenciesToLoad;
|
std::stack<std::string> dependenciesToLoad;
|
||||||
|
|
||||||
if (sndBank->streamAssetBank.zone)
|
if (sndBank.streamAssetBank.zone)
|
||||||
{
|
{
|
||||||
const auto soundBankFileName = SoundBank::GetFileNameForDefinition(true, sndBank->streamAssetBank.zone, sndBank->streamAssetBank.language);
|
const auto soundBankFileName = SoundBank::GetFileNameForDefinition(true, sndBank.streamAssetBank.zone, sndBank.streamAssetBank.language);
|
||||||
LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, &sndBank->streamAssetBank, zone, loadedBanksForZone, dependenciesToLoad);
|
LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, sndBank.streamAssetBank, zone, loadedBanksForZone, dependenciesToLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sndBank->runtimeAssetLoad && sndBank->loadAssetBank.zone)
|
if (sndBank.runtimeAssetLoad && sndBank.loadAssetBank.zone)
|
||||||
{
|
{
|
||||||
const auto soundBankFileName = SoundBank::GetFileNameForDefinition(false, sndBank->loadAssetBank.zone, sndBank->loadAssetBank.language);
|
const auto soundBankFileName = SoundBank::GetFileNameForDefinition(false, sndBank.loadAssetBank.zone, sndBank.loadAssetBank.language);
|
||||||
LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, &sndBank->loadAssetBank, zone, loadedBanksForZone, dependenciesToLoad);
|
LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, sndBank.loadAssetBank, zone, loadedBanksForZone, dependenciesToLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!dependenciesToLoad.empty())
|
while (!dependenciesToLoad.empty())
|
||||||
@ -236,76 +235,72 @@ namespace T6
|
|||||||
loadedBanksForZone.emplace(dependencyFileName);
|
loadedBanksForZone.emplace(dependencyFileName);
|
||||||
|
|
||||||
for (const auto& dependency : soundBank->GetDependencies())
|
for (const auto& dependency : soundBank->GetDependencies())
|
||||||
{
|
|
||||||
dependenciesToLoad.emplace(dependency);
|
dependenciesToLoad.emplace(dependency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone)
|
void ObjLoader::LoadIPakForZone(ISearchPath& searchPath, const std::string& ipakName, Zone& zone)
|
||||||
{
|
{
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
printf("Trying to load ipak '%s' for zone '%s'\n", ipakName.c_str(), zone->m_name.c_str());
|
std::cout << std::format("Trying to load ipak '{}' for zone '{}'\n", ipakName, zone.m_name);
|
||||||
|
|
||||||
auto* existingIPak = IPak::Repository.GetContainerByName(ipakName);
|
auto* existingIPak = IPak::Repository.GetContainerByName(ipakName);
|
||||||
if (existingIPak != nullptr)
|
if (existingIPak != nullptr)
|
||||||
{
|
{
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
printf("Referencing loaded ipak '%s'.\n", ipakName.c_str());
|
std::cout << std::format("Referencing loaded ipak '{}'.\n", ipakName);
|
||||||
|
|
||||||
IPak::Repository.AddContainerReference(existingIPak, zone);
|
IPak::Repository.AddContainerReference(existingIPak, &zone);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ipakFilename = ipakName + ".ipak";
|
const auto ipakFilename = std::format("{}.ipak", ipakName);
|
||||||
|
|
||||||
auto file = searchPath->Open(ipakFilename);
|
auto file = searchPath.Open(ipakFilename);
|
||||||
if (file.IsOpen())
|
if (file.IsOpen())
|
||||||
{
|
{
|
||||||
auto ipak = std::make_unique<IPak>(ipakFilename, std::move(file.m_stream));
|
auto ipak = std::make_unique<IPak>(ipakFilename, std::move(file.m_stream));
|
||||||
|
|
||||||
if (ipak->Initialize())
|
if (ipak->Initialize())
|
||||||
{
|
{
|
||||||
IPak::Repository.AddContainer(std::move(ipak), zone);
|
IPak::Repository.AddContainer(std::move(ipak), &zone);
|
||||||
|
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
printf("Found and loaded ipak '%s'.\n", ipakFilename.c_str());
|
std::cout << std::format("Found and loaded ipak '{}'.\n", ipakFilename);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Failed to load ipak '%s'!\n", ipakFilename.c_str());
|
std::cerr << std::format("Failed to load ipak '{}'!\n", ipakFilename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsMpZone(Zone* zone)
|
bool ObjLoader::IsMpZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
|
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoader::IsZmZone(Zone* zone)
|
bool ObjLoader::IsZmZone(const Zone& zone)
|
||||||
{
|
{
|
||||||
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
|
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::LoadCommonIPaks(ISearchPath* searchPath, Zone* zone)
|
void ObjLoader::LoadCommonIPaks(ISearchPath& searchPath, Zone& zone)
|
||||||
{
|
{
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
printf("Loading common ipaks for zone \"%s\"\n", zone->m_name.c_str());
|
std::cout << std::format("Loading common ipaks for zone \"{}\"\n", zone.m_name);
|
||||||
|
|
||||||
LoadIPakForZone(searchPath, "base", zone);
|
LoadIPakForZone(searchPath, "base", zone);
|
||||||
auto languagePrefixes = g_GameT6.GetLanguagePrefixes();
|
const auto languagePrefixes = g_GameT6.GetLanguagePrefixes();
|
||||||
for (const auto& languagePrefix : languagePrefixes)
|
for (const auto& languagePrefix : languagePrefixes)
|
||||||
{
|
LoadIPakForZone(searchPath, std::format("{}base", languagePrefix.m_prefix), zone);
|
||||||
LoadIPakForZone(searchPath, languagePrefix.m_prefix + "base", zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsMpZone(zone))
|
if (IsMpZone(zone))
|
||||||
{
|
{
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
printf("Loading multiplayer ipaks for zone \"%s\"\n", zone->m_name.c_str());
|
std::cout << std::format("Loading multiplayer ipaks for zone \"{}\"\n", zone.m_name);
|
||||||
|
|
||||||
LoadIPakForZone(searchPath, "mp", zone);
|
LoadIPakForZone(searchPath, "mp", zone);
|
||||||
LoadIPakForZone(searchPath, "so", zone);
|
LoadIPakForZone(searchPath, "so", zone);
|
||||||
@ -313,23 +308,23 @@ namespace T6
|
|||||||
else if (IsZmZone(zone))
|
else if (IsZmZone(zone))
|
||||||
{
|
{
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
printf("Loading zombie ipak for zone \"%s\"\n", zone->m_name.c_str());
|
std::cout << std::format("Loading zombie ipak for zone \"{}\"\n", zone.m_name);
|
||||||
|
|
||||||
LoadIPakForZone(searchPath, "zm", zone);
|
LoadIPakForZone(searchPath, "zm", zone);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
printf("Loading singleplayer ipak for zone \"%s\"\n", zone->m_name.c_str());
|
std::cout << std::format("Loading singleplayer ipak for zone \"{}\"\n", zone.m_name);
|
||||||
|
|
||||||
LoadIPakForZone(searchPath, "sp", zone);
|
LoadIPakForZone(searchPath, "sp", zone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const
|
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const
|
||||||
{
|
{
|
||||||
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone->m_pools.get());
|
const auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone.m_pools.get());
|
||||||
const auto zoneNameHash = Common::Com_HashKey(zone->m_name.c_str(), 64);
|
const auto zoneNameHash = Common::Com_HashKey(zone.m_name.c_str(), 64);
|
||||||
|
|
||||||
LoadCommonIPaks(searchPath, zone);
|
LoadCommonIPaks(searchPath, zone);
|
||||||
|
|
||||||
@ -337,7 +332,7 @@ namespace T6
|
|||||||
{
|
{
|
||||||
for (auto* keyValuePairsEntry : *assetPoolT6->m_key_value_pairs)
|
for (auto* keyValuePairsEntry : *assetPoolT6->m_key_value_pairs)
|
||||||
{
|
{
|
||||||
auto* keyValuePairs = keyValuePairsEntry->Asset();
|
const auto* keyValuePairs = keyValuePairsEntry->Asset();
|
||||||
for (auto variableIndex = 0; variableIndex < keyValuePairs->numVariables; variableIndex++)
|
for (auto variableIndex = 0; variableIndex < keyValuePairs->numVariables; variableIndex++)
|
||||||
{
|
{
|
||||||
auto* variable = &keyValuePairs->keyValuePairs[variableIndex];
|
auto* variable = &keyValuePairs->keyValuePairs[variableIndex];
|
||||||
@ -356,143 +351,23 @@ namespace T6
|
|||||||
|
|
||||||
for (auto* sndBankAssetInfo : *assetPoolT6->m_sound_bank)
|
for (auto* sndBankAssetInfo : *assetPoolT6->m_sound_bank)
|
||||||
{
|
{
|
||||||
LoadSoundBanksFromAsset(searchPath, sndBankAssetInfo->Asset(), zone, loadedSoundBanksForZone);
|
LoadSoundBanksFromAsset(searchPath, *sndBankAssetInfo->Asset(), zone, loadedSoundBanksForZone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::UnloadContainersOfZone(Zone* zone) const
|
void ObjLoader::UnloadContainersOfZone(Zone& zone) const
|
||||||
{
|
{
|
||||||
IPak::Repository.RemoveContainerReferences(zone);
|
IPak::Repository.RemoveContainerReferences(&zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
|
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName) const
|
||||||
{
|
{
|
||||||
const auto* loadDef = image->texture.loadDef;
|
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
|
||||||
Dx12TextureLoader textureLoader(zone->GetMemory());
|
|
||||||
|
|
||||||
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
|
|
||||||
|
|
||||||
if (loadDef->flags & iwi27::IMG_FLAG_VOLMAP)
|
|
||||||
textureLoader.Type(TextureType::T_3D);
|
|
||||||
else if (loadDef->flags & iwi27::IMG_FLAG_CUBEMAP)
|
|
||||||
textureLoader.Type(TextureType::T_CUBE);
|
|
||||||
else
|
|
||||||
textureLoader.Type(TextureType::T_2D);
|
|
||||||
|
|
||||||
textureLoader.Format(static_cast<oat::DXGI_FORMAT>(loadDef->format));
|
|
||||||
textureLoader.HasMipMaps(!(loadDef->flags & iwi27::IMG_FLAG_NOMIPMAPS));
|
|
||||||
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->loadedSize = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->loadedSize += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
Texture* loadedTexture = nullptr;
|
|
||||||
IwiLoader loader(zone->GetMemory());
|
|
||||||
|
|
||||||
if (image->streamedPartCount > 0)
|
|
||||||
{
|
|
||||||
for (auto* ipak : IPak::Repository)
|
|
||||||
{
|
|
||||||
auto ipakStream = ipak->GetEntryStream(image->hash, image->streamedParts[0].hash);
|
|
||||||
|
|
||||||
if (ipakStream)
|
|
||||||
{
|
|
||||||
loadedTexture = loader.LoadIwi(*ipakStream);
|
|
||||||
|
|
||||||
ipakStream->close();
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadedTexture == nullptr)
|
|
||||||
{
|
|
||||||
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto filePathImage = searchPath->Open(imageFileName);
|
|
||||||
if (filePathImage.IsOpen())
|
|
||||||
{
|
|
||||||
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadedTexture != nullptr)
|
|
||||||
{
|
|
||||||
image->texture.texture = loadedTexture;
|
|
||||||
image->loadedSize = 0;
|
|
||||||
|
|
||||||
const auto textureMipCount = loadedTexture->GetMipMapCount();
|
|
||||||
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
|
|
||||||
image->loadedSize += loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Could not find data for image \"%s\"\n", image->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
|
|
||||||
{
|
|
||||||
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone->m_pools.get());
|
|
||||||
|
|
||||||
if (assetPoolT6 && assetPoolT6->m_image != nullptr)
|
|
||||||
{
|
|
||||||
for (auto* imageEntry : *assetPoolT6->m_image)
|
|
||||||
{
|
|
||||||
auto* image = imageEntry->Asset();
|
|
||||||
|
|
||||||
if (image->loadedSize > 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not load linked assets
|
|
||||||
if (image->name && image->name[0] == ',')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
|
||||||
{
|
|
||||||
LoadImageFromLoadDef(image, zone);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LoadImageFromIwi(image, searchPath, zone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
|
|
||||||
{
|
|
||||||
LoadImageData(searchPath, zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, const asset_type_t assetType, const std::string& assetName) const
|
|
||||||
{
|
|
||||||
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
|
|
||||||
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
|
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
|
||||||
{
|
{
|
||||||
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
for (const auto& [type, loader] : m_asset_loaders_by_type)
|
||||||
loader->FinalizeAssetsForZone(context);
|
loader->FinalizeAssetsForZone(context);
|
||||||
|
@ -6,52 +6,44 @@
|
|||||||
#include "ObjContainer/SoundBank/SoundBank.h"
|
#include "ObjContainer/SoundBank/SoundBank.h"
|
||||||
#include "SearchPath/ISearchPath.h"
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace T6
|
namespace T6
|
||||||
{
|
{
|
||||||
class ObjLoader final : public IObjLoader
|
class ObjLoader final : public IObjLoader
|
||||||
{
|
{
|
||||||
static const int IPAK_READ_HASH;
|
|
||||||
static const int GLOBAL_HASH;
|
|
||||||
|
|
||||||
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
|
||||||
|
|
||||||
static bool VerifySoundBankChecksum(const SoundBank* soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank);
|
|
||||||
static SoundBank* LoadSoundBankForZone(ISearchPath* searchPath, const std::string& soundBankFileName, Zone* zone);
|
|
||||||
static void LoadSoundBankFromLinkedInfo(ISearchPath* searchPath,
|
|
||||||
const std::string& soundBankFileName,
|
|
||||||
const SndRuntimeAssetBank* sndBankLinkedInfo,
|
|
||||||
Zone* zone,
|
|
||||||
std::set<std::string>& loadedBanksForZone,
|
|
||||||
std::stack<std::string>& dependenciesToLoad);
|
|
||||||
static void LoadSoundBanksFromAsset(ISearchPath* searchPath, const SndBank* sndBank, Zone* zone, std::set<std::string>& loadedBanksForZone);
|
|
||||||
|
|
||||||
static void LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone);
|
|
||||||
|
|
||||||
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
|
|
||||||
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
|
|
||||||
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
|
|
||||||
|
|
||||||
static bool IsMpZone(Zone* zone);
|
|
||||||
static bool IsZmZone(Zone* zone);
|
|
||||||
static void LoadCommonIPaks(ISearchPath* searchPath, Zone* zone);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjLoader();
|
ObjLoader();
|
||||||
|
|
||||||
bool SupportsZone(Zone* zone) const override;
|
[[nodiscard]] bool SupportsZone(const Zone& zone) const override;
|
||||||
|
|
||||||
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
|
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
|
||||||
void UnloadContainersOfZone(Zone* zone) const override;
|
void UnloadContainersOfZone(Zone& zone) const override;
|
||||||
|
|
||||||
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
|
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
|
||||||
|
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
|
||||||
|
|
||||||
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
|
private:
|
||||||
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
|
static bool VerifySoundBankChecksum(const SoundBank& soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank);
|
||||||
|
static SoundBank* LoadSoundBankForZone(ISearchPath& searchPath, const std::string& soundBankFileName, Zone& zone);
|
||||||
|
static void LoadSoundBankFromLinkedInfo(ISearchPath& searchPath,
|
||||||
|
const std::string& soundBankFileName,
|
||||||
|
const SndRuntimeAssetBank& sndBankLinkedInfo,
|
||||||
|
Zone& zone,
|
||||||
|
std::set<std::string>& loadedBanksForZone,
|
||||||
|
std::stack<std::string>& dependenciesToLoad);
|
||||||
|
static void LoadSoundBanksFromAsset(ISearchPath& searchPath, const SndBank& sndBank, Zone& zone, std::set<std::string>& loadedBanksForZone);
|
||||||
|
|
||||||
|
static void LoadIPakForZone(ISearchPath& searchPath, const std::string& ipakName, Zone& zone);
|
||||||
|
static void LoadCommonIPaks(ISearchPath& searchPath, Zone& zone);
|
||||||
|
|
||||||
|
static bool IsMpZone(const Zone& zone);
|
||||||
|
static bool IsZmZone(const Zone& zone);
|
||||||
|
|
||||||
|
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
|
||||||
};
|
};
|
||||||
} // namespace T6
|
} // namespace T6
|
||||||
|
@ -7,35 +7,33 @@
|
|||||||
class IObjLoader
|
class IObjLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
IObjLoader() = default;
|
||||||
virtual ~IObjLoader() = default;
|
virtual ~IObjLoader() = default;
|
||||||
|
IObjLoader(const IObjLoader& other) = default;
|
||||||
|
IObjLoader(IObjLoader&& other) noexcept = default;
|
||||||
|
IObjLoader& operator=(const IObjLoader& other) = default;
|
||||||
|
IObjLoader& operator=(IObjLoader&& other) noexcept = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Checks whether this ObjLoader supports a specified zone.
|
* \brief Checks whether this ObjLoader supports a specified zone.
|
||||||
* \param zone The zone to check.
|
* \param zone The zone to check.
|
||||||
* \return \c true if the specified zone is supported.
|
* \return \c true if the specified zone is supported.
|
||||||
*/
|
*/
|
||||||
virtual bool SupportsZone(Zone* zone) const = 0;
|
[[nodiscard]] virtual bool SupportsZone(const Zone& zone) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Loads all containers that are referenced by a specified zone.
|
* \brief Loads all containers that are referenced by a specified zone.
|
||||||
* \param searchPath The search path object to use to find the referenced containers.
|
* \param searchPath The search path object to use to find the referenced containers.
|
||||||
* \param zone The zone to check for referenced containers.
|
* \param zone The zone to check for referenced containers.
|
||||||
*/
|
*/
|
||||||
virtual void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const = 0;
|
virtual void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Unloads all containers of a specified zone. If a container is also loaded by another zone it will only be unloaded when all referencing zones are
|
* \brief Unloads all containers of a specified zone. If a container is also loaded by another zone it will only be unloaded when all referencing zones are
|
||||||
* unloaded. \param zone The zone to unload all containers for.
|
* unloaded. \param zone The zone to unload all containers for.
|
||||||
*/
|
*/
|
||||||
virtual void UnloadContainersOfZone(Zone* zone) const = 0;
|
virtual void UnloadContainersOfZone(Zone& zone) const = 0;
|
||||||
|
|
||||||
/**
|
virtual bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const = 0;
|
||||||
* \brief Loads the obj data for all assets of a specified zone.
|
virtual void FinalizeAssetsForZone(AssetLoadingContext& context) const = 0;
|
||||||
* \param searchPath The search path object to use to find obj files.
|
|
||||||
* \param zone The zone of the assets to load the obj data for.
|
|
||||||
*/
|
|
||||||
virtual void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const = 0;
|
|
||||||
|
|
||||||
virtual bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const = 0;
|
|
||||||
virtual void FinalizeAssetsForZone(AssetLoadingContext* context) const = 0;
|
|
||||||
};
|
};
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
Dx12TextureLoader::Dx12TextureLoader(MemoryManager* memoryManager)
|
Dx12TextureLoader::Dx12TextureLoader()
|
||||||
: m_memory_manager(memoryManager),
|
: m_format(oat::DXGI_FORMAT_UNKNOWN),
|
||||||
m_format(oat::DXGI_FORMAT_UNKNOWN),
|
|
||||||
m_type(TextureType::T_2D),
|
m_type(TextureType::T_2D),
|
||||||
m_has_mip_maps(false),
|
m_has_mip_maps(false),
|
||||||
m_width(1u),
|
m_width(1u),
|
||||||
@ -60,26 +59,26 @@ Dx12TextureLoader& Dx12TextureLoader::Depth(const size_t depth)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Dx12TextureLoader::LoadTexture(const void* data)
|
std::unique_ptr<Texture> Dx12TextureLoader::LoadTexture(const void* data)
|
||||||
{
|
{
|
||||||
const auto* format = GetFormatForDx12Format();
|
const auto* format = GetFormatForDx12Format();
|
||||||
|
|
||||||
if (format == nullptr)
|
if (format == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Texture* texture;
|
std::unique_ptr<Texture> texture;
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case TextureType::T_2D:
|
case TextureType::T_2D:
|
||||||
texture = m_memory_manager->Create<Texture2D>(format, m_width, m_height, m_has_mip_maps);
|
texture = std::make_unique<Texture2D>(format, m_width, m_height, m_has_mip_maps);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextureType::T_3D:
|
case TextureType::T_3D:
|
||||||
texture = m_memory_manager->Create<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
|
texture = std::make_unique<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextureType::T_CUBE:
|
case TextureType::T_CUBE:
|
||||||
texture = m_memory_manager->Create<TextureCube>(format, m_width, m_width, m_has_mip_maps);
|
texture = std::make_unique<TextureCube>(format, m_width, m_width, m_has_mip_maps);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -5,24 +5,13 @@
|
|||||||
#include "Utils/ClassUtils.h"
|
#include "Utils/ClassUtils.h"
|
||||||
#include "Utils/MemoryManager.h"
|
#include "Utils/MemoryManager.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class Dx12TextureLoader
|
class Dx12TextureLoader
|
||||||
{
|
{
|
||||||
static std::unordered_map<ImageFormatId, ImageFormatId> m_conversion_table;
|
|
||||||
|
|
||||||
MemoryManager* m_memory_manager;
|
|
||||||
oat::DXGI_FORMAT m_format;
|
|
||||||
TextureType m_type;
|
|
||||||
bool m_has_mip_maps;
|
|
||||||
size_t m_width;
|
|
||||||
size_t m_height;
|
|
||||||
size_t m_depth;
|
|
||||||
|
|
||||||
_NODISCARD const ImageFormat* GetFormatForDx12Format() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Dx12TextureLoader(MemoryManager* memoryManager);
|
Dx12TextureLoader();
|
||||||
|
|
||||||
Dx12TextureLoader& Format(oat::DXGI_FORMAT format);
|
Dx12TextureLoader& Format(oat::DXGI_FORMAT format);
|
||||||
Dx12TextureLoader& Type(TextureType textureType);
|
Dx12TextureLoader& Type(TextureType textureType);
|
||||||
@ -31,5 +20,17 @@ public:
|
|||||||
Dx12TextureLoader& Height(size_t height);
|
Dx12TextureLoader& Height(size_t height);
|
||||||
Dx12TextureLoader& Depth(size_t depth);
|
Dx12TextureLoader& Depth(size_t depth);
|
||||||
|
|
||||||
Texture* LoadTexture(const void* data);
|
std::unique_ptr<Texture> LoadTexture(const void* data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
_NODISCARD const ImageFormat* GetFormatForDx12Format() const;
|
||||||
|
|
||||||
|
static std::unordered_map<ImageFormatId, ImageFormatId> m_conversion_table;
|
||||||
|
|
||||||
|
oat::DXGI_FORMAT m_format;
|
||||||
|
TextureType m_type;
|
||||||
|
bool m_has_mip_maps;
|
||||||
|
size_t m_width;
|
||||||
|
size_t m_height;
|
||||||
|
size_t m_depth;
|
||||||
};
|
};
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
Dx9TextureLoader::Dx9TextureLoader(MemoryManager* memoryManager)
|
Dx9TextureLoader::Dx9TextureLoader()
|
||||||
: m_memory_manager(memoryManager),
|
: m_format(oat::D3DFMT_UNKNOWN),
|
||||||
m_format(oat::D3DFMT_UNKNOWN),
|
|
||||||
m_type(TextureType::T_2D),
|
m_type(TextureType::T_2D),
|
||||||
m_has_mip_maps(false),
|
m_has_mip_maps(false),
|
||||||
m_width(1u),
|
m_width(1u),
|
||||||
@ -15,7 +14,7 @@ Dx9TextureLoader::Dx9TextureLoader(MemoryManager* memoryManager)
|
|||||||
|
|
||||||
const ImageFormat* Dx9TextureLoader::GetFormatForDx9Format() const
|
const ImageFormat* Dx9TextureLoader::GetFormatForDx9Format() const
|
||||||
{
|
{
|
||||||
for (auto i : ImageFormat::ALL_FORMATS)
|
for (const auto* i : ImageFormat::ALL_FORMATS)
|
||||||
{
|
{
|
||||||
if (i->GetD3DFormat() == m_format)
|
if (i->GetD3DFormat() == m_format)
|
||||||
return i;
|
return i;
|
||||||
@ -60,26 +59,26 @@ Dx9TextureLoader& Dx9TextureLoader::Depth(const size_t depth)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Dx9TextureLoader::LoadTexture(const void* data)
|
std::unique_ptr<Texture> Dx9TextureLoader::LoadTexture(const void* data)
|
||||||
{
|
{
|
||||||
const auto* format = GetFormatForDx9Format();
|
const auto* format = GetFormatForDx9Format();
|
||||||
|
|
||||||
if (format == nullptr)
|
if (format == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Texture* texture;
|
std::unique_ptr<Texture> texture;
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case TextureType::T_2D:
|
case TextureType::T_2D:
|
||||||
texture = m_memory_manager->Create<Texture2D>(format, m_width, m_height, m_has_mip_maps);
|
texture = std::make_unique<Texture2D>(format, m_width, m_height, m_has_mip_maps);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextureType::T_3D:
|
case TextureType::T_3D:
|
||||||
texture = m_memory_manager->Create<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
|
texture = std::make_unique<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextureType::T_CUBE:
|
case TextureType::T_CUBE:
|
||||||
texture = m_memory_manager->Create<TextureCube>(format, m_width, m_width, m_has_mip_maps);
|
texture = std::make_unique<TextureCube>(format, m_width, m_width, m_has_mip_maps);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -5,22 +5,13 @@
|
|||||||
#include "Utils/ClassUtils.h"
|
#include "Utils/ClassUtils.h"
|
||||||
#include "Utils/MemoryManager.h"
|
#include "Utils/MemoryManager.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class Dx9TextureLoader
|
class Dx9TextureLoader
|
||||||
{
|
{
|
||||||
MemoryManager* m_memory_manager;
|
|
||||||
oat::D3DFORMAT m_format;
|
|
||||||
TextureType m_type;
|
|
||||||
bool m_has_mip_maps;
|
|
||||||
size_t m_width;
|
|
||||||
size_t m_height;
|
|
||||||
size_t m_depth;
|
|
||||||
|
|
||||||
_NODISCARD const ImageFormat* GetFormatForDx9Format() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Dx9TextureLoader(MemoryManager* memoryManager);
|
Dx9TextureLoader();
|
||||||
|
|
||||||
Dx9TextureLoader& Format(oat::D3DFORMAT format);
|
Dx9TextureLoader& Format(oat::D3DFORMAT format);
|
||||||
Dx9TextureLoader& Type(TextureType textureType);
|
Dx9TextureLoader& Type(TextureType textureType);
|
||||||
@ -29,5 +20,15 @@ public:
|
|||||||
Dx9TextureLoader& Height(size_t height);
|
Dx9TextureLoader& Height(size_t height);
|
||||||
Dx9TextureLoader& Depth(size_t depth);
|
Dx9TextureLoader& Depth(size_t depth);
|
||||||
|
|
||||||
Texture* LoadTexture(const void* data);
|
std::unique_ptr<Texture> LoadTexture(const void* data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
_NODISCARD const ImageFormat* GetFormatForDx9Format() const;
|
||||||
|
|
||||||
|
oat::D3DFORMAT m_format;
|
||||||
|
TextureType m_type;
|
||||||
|
bool m_has_mip_maps;
|
||||||
|
size_t m_width;
|
||||||
|
size_t m_height;
|
||||||
|
size_t m_depth;
|
||||||
};
|
};
|
||||||
|
@ -3,15 +3,14 @@
|
|||||||
#include "Image/IwiTypes.h"
|
#include "Image/IwiTypes.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <format>
|
||||||
|
#include <iostream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
IwiLoader::IwiLoader(MemoryManager* memoryManager)
|
namespace iwi
|
||||||
{
|
|
||||||
m_memory_manager = memoryManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ImageFormat* IwiLoader::GetFormat6(int8_t format)
|
|
||||||
{
|
{
|
||||||
|
const ImageFormat* GetFormat6(int8_t format)
|
||||||
|
{
|
||||||
switch (static_cast<iwi6::IwiFormat>(format))
|
switch (static_cast<iwi6::IwiFormat>(format))
|
||||||
{
|
{
|
||||||
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
|
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
|
||||||
@ -37,18 +36,18 @@ const ImageFormat* IwiLoader::GetFormat6(int8_t format)
|
|||||||
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
|
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
|
||||||
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
|
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
|
||||||
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
|
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
|
||||||
printf("Unsupported IWI format: %i\n", format);
|
std::cerr << std::format("Unsupported IWI format: {}\n", format);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unknown IWI format: %i\n", format);
|
std::cerr << std::format("Unknown IWI format: {}\n", format);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* IwiLoader::LoadIwi6(std::istream& stream) const
|
std::unique_ptr<Texture> LoadIwi6(std::istream& stream)
|
||||||
{
|
{
|
||||||
iwi6::IwiHeader header{};
|
iwi6::IwiHeader header{};
|
||||||
|
|
||||||
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
||||||
@ -64,19 +63,13 @@ Texture* IwiLoader::LoadIwi6(std::istream& stream) const
|
|||||||
auto depth = header.dimensions[2];
|
auto depth = header.dimensions[2];
|
||||||
auto hasMipMaps = !(header.flags & iwi6::IwiFlags::IMG_FLAG_NOMIPMAPS);
|
auto hasMipMaps = !(header.flags & iwi6::IwiFlags::IMG_FLAG_NOMIPMAPS);
|
||||||
|
|
||||||
Texture* texture;
|
std::unique_ptr<Texture> texture;
|
||||||
if (header.flags & iwi6::IwiFlags::IMG_FLAG_CUBEMAP)
|
if (header.flags & iwi6::IwiFlags::IMG_FLAG_CUBEMAP)
|
||||||
{
|
texture = std::make_unique<TextureCube>(format, width, height, hasMipMaps);
|
||||||
texture = m_memory_manager->Create<TextureCube>(format, width, height, hasMipMaps);
|
|
||||||
}
|
|
||||||
else if (header.flags & iwi6::IwiFlags::IMG_FLAG_VOLMAP)
|
else if (header.flags & iwi6::IwiFlags::IMG_FLAG_VOLMAP)
|
||||||
{
|
texture = std::make_unique<Texture3D>(format, width, height, depth, hasMipMaps);
|
||||||
texture = m_memory_manager->Create<Texture3D>(format, width, height, depth, hasMipMaps);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
texture = std::make_unique<Texture2D>(format, width, height, hasMipMaps);
|
||||||
texture = m_memory_manager->Create<Texture2D>(format, width, height, hasMipMaps);
|
|
||||||
}
|
|
||||||
|
|
||||||
texture->Allocate();
|
texture->Allocate();
|
||||||
|
|
||||||
@ -91,27 +84,23 @@ Texture* IwiLoader::LoadIwi6(std::istream& stream) const
|
|||||||
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi6::IwiHeader::fileSizeForPicmip)>)
|
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi6::IwiHeader::fileSizeForPicmip)>)
|
||||||
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
||||||
{
|
{
|
||||||
printf("Iwi has invalid file size for picmip %i\n", currentMipLevel);
|
std::cerr << std::format("Iwi has invalid file size for picmip {}\n", currentMipLevel);
|
||||||
|
|
||||||
m_memory_manager->Delete(texture);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
||||||
if (stream.gcount() != sizeOfMipLevel)
|
if (stream.gcount() != sizeOfMipLevel)
|
||||||
{
|
{
|
||||||
printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel);
|
std::cerr << std::format("Unexpected eof of iwi in mip level {}\n", currentMipLevel);
|
||||||
|
|
||||||
m_memory_manager->Delete(texture);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImageFormat* IwiLoader::GetFormat8(int8_t format)
|
const ImageFormat* GetFormat8(int8_t format)
|
||||||
{
|
{
|
||||||
switch (static_cast<iwi8::IwiFormat>(format))
|
switch (static_cast<iwi8::IwiFormat>(format))
|
||||||
{
|
{
|
||||||
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
|
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
|
||||||
@ -145,18 +134,18 @@ const ImageFormat* IwiLoader::GetFormat8(int8_t format)
|
|||||||
case iwi8::IwiFormat::IMG_FORMAT_DXN_AS_LUMINANCE_ALPHA:
|
case iwi8::IwiFormat::IMG_FORMAT_DXN_AS_LUMINANCE_ALPHA:
|
||||||
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_LUMINANCE:
|
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_LUMINANCE:
|
||||||
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_ALPHA:
|
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_ALPHA:
|
||||||
printf("Unsupported IWI format: %i\n", format);
|
std::cerr << std::format("Unsupported IWI format: {}\n", format);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unknown IWI format: %i\n", format);
|
std::cerr << std::format("Unknown IWI format: {}\n", format);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* IwiLoader::LoadIwi8(std::istream& stream) const
|
std::unique_ptr<Texture> LoadIwi8(std::istream& stream)
|
||||||
{
|
{
|
||||||
iwi8::IwiHeader header{};
|
iwi8::IwiHeader header{};
|
||||||
|
|
||||||
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
||||||
@ -172,27 +161,27 @@ Texture* IwiLoader::LoadIwi8(std::istream& stream) const
|
|||||||
auto depth = header.dimensions[2];
|
auto depth = header.dimensions[2];
|
||||||
auto hasMipMaps = !(header.flags & iwi8::IwiFlags::IMG_FLAG_NOMIPMAPS);
|
auto hasMipMaps = !(header.flags & iwi8::IwiFlags::IMG_FLAG_NOMIPMAPS);
|
||||||
|
|
||||||
Texture* texture;
|
std::unique_ptr<Texture> texture;
|
||||||
if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_CUBE)
|
if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_CUBE)
|
||||||
{
|
{
|
||||||
texture = m_memory_manager->Create<TextureCube>(format, width, height, hasMipMaps);
|
texture = std::make_unique<TextureCube>(format, width, height, hasMipMaps);
|
||||||
}
|
}
|
||||||
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_3D)
|
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_3D)
|
||||||
{
|
{
|
||||||
texture = m_memory_manager->Create<Texture3D>(format, width, height, depth, hasMipMaps);
|
texture = std::make_unique<Texture3D>(format, width, height, depth, hasMipMaps);
|
||||||
}
|
}
|
||||||
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_2D)
|
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_2D)
|
||||||
{
|
{
|
||||||
texture = m_memory_manager->Create<Texture2D>(format, width, height, hasMipMaps);
|
texture = std::make_unique<Texture2D>(format, width, height, hasMipMaps);
|
||||||
}
|
}
|
||||||
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_1D)
|
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_1D)
|
||||||
{
|
{
|
||||||
printf("Iwi has unsupported map type 1D\n");
|
std::cerr << "Iwi has unsupported map type 1D\n";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Iwi has unsupported map type\n");
|
std::cerr << "Iwi has unsupported map type\n";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,27 +198,23 @@ Texture* IwiLoader::LoadIwi8(std::istream& stream) const
|
|||||||
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi8::IwiHeader::fileSizeForPicmip)>)
|
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi8::IwiHeader::fileSizeForPicmip)>)
|
||||||
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
||||||
{
|
{
|
||||||
printf("Iwi has invalid file size for picmip %i\n", currentMipLevel);
|
std::cerr << std::format("Iwi has invalid file size for picmip {}\n", currentMipLevel);
|
||||||
|
|
||||||
m_memory_manager->Delete(texture);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
||||||
if (stream.gcount() != sizeOfMipLevel)
|
if (stream.gcount() != sizeOfMipLevel)
|
||||||
{
|
{
|
||||||
printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel);
|
std::cerr << std::format("Unexpected eof of iwi in mip level {}\n", currentMipLevel);
|
||||||
|
|
||||||
m_memory_manager->Delete(texture);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImageFormat* IwiLoader::GetFormat13(int8_t format)
|
const ImageFormat* GetFormat13(int8_t format)
|
||||||
{
|
{
|
||||||
switch (static_cast<iwi13::IwiFormat>(format))
|
switch (static_cast<iwi13::IwiFormat>(format))
|
||||||
{
|
{
|
||||||
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
|
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
|
||||||
@ -260,18 +245,18 @@ const ImageFormat* IwiLoader::GetFormat13(int8_t format)
|
|||||||
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_C8:
|
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_C8:
|
||||||
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGBA8:
|
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGBA8:
|
||||||
case iwi13::IwiFormat::IMG_FORMAT_A16B16G16R16F:
|
case iwi13::IwiFormat::IMG_FORMAT_A16B16G16R16F:
|
||||||
printf("Unsupported IWI format: %i\n", format);
|
std::cerr << std::format("Unsupported IWI format: {}\n", format);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unknown IWI format: %i\n", format);
|
std::cerr << std::format("Unknown IWI format: {}\n", format);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* IwiLoader::LoadIwi13(std::istream& stream) const
|
std::unique_ptr<Texture> LoadIwi13(std::istream& stream)
|
||||||
{
|
{
|
||||||
iwi13::IwiHeader header{};
|
iwi13::IwiHeader header{};
|
||||||
|
|
||||||
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
||||||
@ -287,19 +272,13 @@ Texture* IwiLoader::LoadIwi13(std::istream& stream) const
|
|||||||
auto depth = header.dimensions[2];
|
auto depth = header.dimensions[2];
|
||||||
auto hasMipMaps = !(header.flags & iwi13::IwiFlags::IMG_FLAG_NOMIPMAPS);
|
auto hasMipMaps = !(header.flags & iwi13::IwiFlags::IMG_FLAG_NOMIPMAPS);
|
||||||
|
|
||||||
Texture* texture;
|
std::unique_ptr<Texture> texture;
|
||||||
if (header.flags & iwi13::IwiFlags::IMG_FLAG_CUBEMAP)
|
if (header.flags & iwi13::IwiFlags::IMG_FLAG_CUBEMAP)
|
||||||
{
|
texture = std::make_unique<TextureCube>(format, width, height, hasMipMaps);
|
||||||
texture = m_memory_manager->Create<TextureCube>(format, width, height, hasMipMaps);
|
|
||||||
}
|
|
||||||
else if (header.flags & iwi13::IwiFlags::IMG_FLAG_VOLMAP)
|
else if (header.flags & iwi13::IwiFlags::IMG_FLAG_VOLMAP)
|
||||||
{
|
texture = std::make_unique<Texture3D>(format, width, height, depth, hasMipMaps);
|
||||||
texture = m_memory_manager->Create<Texture3D>(format, width, height, depth, hasMipMaps);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
texture = std::make_unique<Texture2D>(format, width, height, hasMipMaps);
|
||||||
texture = m_memory_manager->Create<Texture2D>(format, width, height, hasMipMaps);
|
|
||||||
}
|
|
||||||
|
|
||||||
texture->Allocate();
|
texture->Allocate();
|
||||||
|
|
||||||
@ -314,27 +293,23 @@ Texture* IwiLoader::LoadIwi13(std::istream& stream) const
|
|||||||
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi13::IwiHeader::fileSizeForPicmip)>)
|
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi13::IwiHeader::fileSizeForPicmip)>)
|
||||||
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
||||||
{
|
{
|
||||||
printf("Iwi has invalid file size for picmip %i\n", currentMipLevel);
|
std::cerr << std::format("Iwi has invalid file size for picmip {}\n", currentMipLevel);
|
||||||
|
|
||||||
m_memory_manager->Delete(texture);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
||||||
if (stream.gcount() != sizeOfMipLevel)
|
if (stream.gcount() != sizeOfMipLevel)
|
||||||
{
|
{
|
||||||
printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel);
|
std::cerr << std::format("Unexpected eof of iwi in mip level {}\n", currentMipLevel);
|
||||||
|
|
||||||
m_memory_manager->Delete(texture);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImageFormat* IwiLoader::GetFormat27(int8_t format)
|
const ImageFormat* GetFormat27(int8_t format)
|
||||||
{
|
{
|
||||||
switch (static_cast<iwi27::IwiFormat>(format))
|
switch (static_cast<iwi27::IwiFormat>(format))
|
||||||
{
|
{
|
||||||
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
|
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
|
||||||
@ -367,18 +342,18 @@ const ImageFormat* IwiLoader::GetFormat27(int8_t format)
|
|||||||
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGB5A3:
|
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGB5A3:
|
||||||
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_C8:
|
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_C8:
|
||||||
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGBA8:
|
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGBA8:
|
||||||
printf("Unsupported IWI format: %i\n", format);
|
std::cerr << std::format("Unsupported IWI format: {}\n", format);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unknown IWI format: %i\n", format);
|
std::cerr << std::format("Unknown IWI format: {}\n", format);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* IwiLoader::LoadIwi27(std::istream& stream) const
|
std::unique_ptr<Texture> LoadIwi27(std::istream& stream)
|
||||||
{
|
{
|
||||||
iwi27::IwiHeader header{};
|
iwi27::IwiHeader header{};
|
||||||
|
|
||||||
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
||||||
@ -394,19 +369,13 @@ Texture* IwiLoader::LoadIwi27(std::istream& stream) const
|
|||||||
auto depth = header.dimensions[2];
|
auto depth = header.dimensions[2];
|
||||||
auto hasMipMaps = !(header.flags & iwi27::IwiFlags::IMG_FLAG_NOMIPMAPS);
|
auto hasMipMaps = !(header.flags & iwi27::IwiFlags::IMG_FLAG_NOMIPMAPS);
|
||||||
|
|
||||||
Texture* texture;
|
std::unique_ptr<Texture> texture;
|
||||||
if (header.flags & iwi27::IwiFlags::IMG_FLAG_CUBEMAP)
|
if (header.flags & iwi27::IwiFlags::IMG_FLAG_CUBEMAP)
|
||||||
{
|
texture = std::make_unique<TextureCube>(format, width, height, hasMipMaps);
|
||||||
texture = m_memory_manager->Create<TextureCube>(format, width, height, hasMipMaps);
|
|
||||||
}
|
|
||||||
else if (header.flags & iwi27::IwiFlags::IMG_FLAG_VOLMAP)
|
else if (header.flags & iwi27::IwiFlags::IMG_FLAG_VOLMAP)
|
||||||
{
|
texture = std::make_unique<Texture3D>(format, width, height, depth, hasMipMaps);
|
||||||
texture = m_memory_manager->Create<Texture3D>(format, width, height, depth, hasMipMaps);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
texture = std::make_unique<Texture2D>(format, width, height, hasMipMaps);
|
||||||
texture = m_memory_manager->Create<Texture2D>(format, width, height, hasMipMaps);
|
|
||||||
}
|
|
||||||
|
|
||||||
texture->Allocate();
|
texture->Allocate();
|
||||||
|
|
||||||
@ -421,27 +390,23 @@ Texture* IwiLoader::LoadIwi27(std::istream& stream) const
|
|||||||
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi27::IwiHeader::fileSizeForPicmip)>)
|
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi27::IwiHeader::fileSizeForPicmip)>)
|
||||||
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
||||||
{
|
{
|
||||||
printf("Iwi has invalid file size for picmip %i\n", currentMipLevel);
|
std::cerr << std::format("Iwi has invalid file size for picmip {}\n", currentMipLevel);
|
||||||
|
|
||||||
m_memory_manager->Delete(texture);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
||||||
if (stream.gcount() != sizeOfMipLevel)
|
if (stream.gcount() != sizeOfMipLevel)
|
||||||
{
|
{
|
||||||
printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel);
|
std::cerr << std::format("Unexpected eof of iwi in mip level {}\n", currentMipLevel);
|
||||||
|
|
||||||
m_memory_manager->Delete(texture);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* IwiLoader::LoadIwi(std::istream& stream)
|
std::unique_ptr<Texture> LoadIwi(std::istream& stream)
|
||||||
{
|
{
|
||||||
IwiVersion iwiVersion{};
|
IwiVersion iwiVersion{};
|
||||||
|
|
||||||
stream.read(reinterpret_cast<char*>(&iwiVersion), sizeof(iwiVersion));
|
stream.read(reinterpret_cast<char*>(&iwiVersion), sizeof(iwiVersion));
|
||||||
@ -450,7 +415,8 @@ Texture* IwiLoader::LoadIwi(std::istream& stream)
|
|||||||
|
|
||||||
if (iwiVersion.tag[0] != 'I' || iwiVersion.tag[1] != 'W' || iwiVersion.tag[2] != 'i')
|
if (iwiVersion.tag[0] != 'I' || iwiVersion.tag[1] != 'W' || iwiVersion.tag[2] != 'i')
|
||||||
{
|
{
|
||||||
printf("Invalid IWI magic\n");
|
std::cerr << "Invalid IWI magic\n";
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (iwiVersion.version)
|
switch (iwiVersion.version)
|
||||||
@ -471,6 +437,7 @@ Texture* IwiLoader::LoadIwi(std::istream& stream)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Unknown IWI version %i\n", iwiVersion.version);
|
std::cerr << std::format("Unknown IWI version {}\n", iwiVersion.version);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
} // namespace iwi
|
||||||
|
@ -1,28 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Image/Texture.h"
|
#include "Image/Texture.h"
|
||||||
#include "Utils/MemoryManager.h"
|
|
||||||
|
|
||||||
#include <istream>
|
#include <istream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class IwiLoader
|
namespace iwi
|
||||||
{
|
{
|
||||||
MemoryManager* m_memory_manager;
|
std::unique_ptr<Texture> LoadIwi(std::istream& stream);
|
||||||
|
}; // namespace iwi
|
||||||
static const ImageFormat* GetFormat6(int8_t format);
|
|
||||||
Texture* LoadIwi6(std::istream& stream) const;
|
|
||||||
|
|
||||||
static const ImageFormat* GetFormat8(int8_t format);
|
|
||||||
Texture* LoadIwi8(std::istream& stream) const;
|
|
||||||
|
|
||||||
static const ImageFormat* GetFormat13(int8_t format);
|
|
||||||
Texture* LoadIwi13(std::istream& stream) const;
|
|
||||||
|
|
||||||
static const ImageFormat* GetFormat27(int8_t format);
|
|
||||||
Texture* LoadIwi27(std::istream& stream) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit IwiLoader(MemoryManager* memoryManager);
|
|
||||||
|
|
||||||
Texture* LoadIwi(std::istream& stream);
|
|
||||||
};
|
|
||||||
|
@ -29,8 +29,6 @@ template<typename ContainerType, typename ReferencerType> class ObjContainerRepo
|
|||||||
ObjContainerEntry& operator=(ObjContainerEntry&& other) noexcept = default;
|
ObjContainerEntry& operator=(ObjContainerEntry&& other) noexcept = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<ObjContainerEntry> m_containers;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjContainerRepository() = default;
|
ObjContainerRepository() = default;
|
||||||
~ObjContainerRepository() = default;
|
~ObjContainerRepository() = default;
|
||||||
@ -120,4 +118,7 @@ public:
|
|||||||
return entry.m_container.get();
|
return entry.m_container.get();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<ObjContainerEntry> m_containers;
|
||||||
};
|
};
|
||||||
|
@ -22,7 +22,7 @@ const IObjLoader* const OBJ_LOADERS[]{
|
|||||||
new T6::ObjLoader(),
|
new T6::ObjLoader(),
|
||||||
};
|
};
|
||||||
|
|
||||||
void ObjLoading::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone)
|
void ObjLoading::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone)
|
||||||
{
|
{
|
||||||
for (const auto* loader : OBJ_LOADERS)
|
for (const auto* loader : OBJ_LOADERS)
|
||||||
{
|
{
|
||||||
@ -34,19 +34,7 @@ void ObjLoading::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoading::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone)
|
void ObjLoading::UnloadContainersOfZone(Zone& zone)
|
||||||
{
|
|
||||||
for (const auto* loader : OBJ_LOADERS)
|
|
||||||
{
|
|
||||||
if (loader->SupportsZone(zone))
|
|
||||||
{
|
|
||||||
loader->LoadObjDataForZone(searchPath, zone);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjLoading::UnloadContainersOfZone(Zone* zone)
|
|
||||||
{
|
{
|
||||||
for (const auto* loader : OBJ_LOADERS)
|
for (const auto* loader : OBJ_LOADERS)
|
||||||
{
|
{
|
||||||
@ -58,10 +46,10 @@ void ObjLoading::UnloadContainersOfZone(Zone* zone)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoading::LoadIWDsInSearchPath(ISearchPath* searchPath)
|
void ObjLoading::LoadIWDsInSearchPath(ISearchPath& searchPath)
|
||||||
{
|
{
|
||||||
searchPath->Find(SearchPathSearchOptions().IncludeSubdirectories(false).FilterExtensions("iwd"),
|
searchPath.Find(SearchPathSearchOptions().IncludeSubdirectories(false).FilterExtensions("iwd"),
|
||||||
[searchPath](const std::string& path)
|
[&searchPath](const std::string& path)
|
||||||
{
|
{
|
||||||
auto file = std::make_unique<std::ifstream>(path, std::fstream::in | std::fstream::binary);
|
auto file = std::make_unique<std::ifstream>(path, std::fstream::in | std::fstream::binary);
|
||||||
|
|
||||||
@ -71,15 +59,15 @@ void ObjLoading::LoadIWDsInSearchPath(ISearchPath* searchPath)
|
|||||||
|
|
||||||
if (iwd->Initialize())
|
if (iwd->Initialize())
|
||||||
{
|
{
|
||||||
IWD::Repository.AddContainer(std::move(iwd), searchPath);
|
IWD::Repository.AddContainer(std::move(iwd), &searchPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoading::UnloadIWDsInSearchPath(ISearchPath* searchPath)
|
void ObjLoading::UnloadIWDsInSearchPath(ISearchPath& searchPath)
|
||||||
{
|
{
|
||||||
IWD::Repository.RemoveContainerReferences(searchPath);
|
IWD::Repository.RemoveContainerReferences(&searchPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchPaths ObjLoading::GetIWDSearchPaths()
|
SearchPaths ObjLoading::GetIWDSearchPaths()
|
||||||
@ -94,11 +82,11 @@ SearchPaths ObjLoading::GetIWDSearchPaths()
|
|||||||
return iwdPaths;
|
return iwdPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjLoading::LoadAssetForZone(AssetLoadingContext* context, const asset_type_t assetType, const std::string& assetName)
|
bool ObjLoading::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName)
|
||||||
{
|
{
|
||||||
for (const auto* loader : OBJ_LOADERS)
|
for (const auto* loader : OBJ_LOADERS)
|
||||||
{
|
{
|
||||||
if (loader->SupportsZone(context->m_zone))
|
if (loader->SupportsZone(context.m_zone))
|
||||||
{
|
{
|
||||||
return loader->LoadAssetForZone(context, assetType, assetName);
|
return loader->LoadAssetForZone(context, assetType, assetName);
|
||||||
}
|
}
|
||||||
@ -107,11 +95,11 @@ bool ObjLoading::LoadAssetForZone(AssetLoadingContext* context, const asset_type
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjLoading::FinalizeAssetsForZone(AssetLoadingContext* context)
|
void ObjLoading::FinalizeAssetsForZone(AssetLoadingContext& context)
|
||||||
{
|
{
|
||||||
for (const auto* loader : OBJ_LOADERS)
|
for (const auto* loader : OBJ_LOADERS)
|
||||||
{
|
{
|
||||||
if (loader->SupportsZone(context->m_zone))
|
if (loader->SupportsZone(context.m_zone))
|
||||||
{
|
{
|
||||||
loader->FinalizeAssetsForZone(context);
|
loader->FinalizeAssetsForZone(context);
|
||||||
return;
|
return;
|
||||||
|
@ -21,25 +21,25 @@ public:
|
|||||||
* \param searchPath The search path to use to find the referenced containers.
|
* \param searchPath The search path to use to find the referenced containers.
|
||||||
* \param zone The zone to load all referenced containers of.
|
* \param zone The zone to load all referenced containers of.
|
||||||
*/
|
*/
|
||||||
static void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone);
|
static void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Unloads all containers that were referenced by a specified zone. If referenced by more than one zone a container will only be unloaded once all
|
* \brief Unloads all containers that were referenced by a specified zone. If referenced by more than one zone a container will only be unloaded once all
|
||||||
* referencing zones were unloaded the container. \param zone The zone to unload all referenced containers for.
|
* referencing zones were unloaded the container. \param zone The zone to unload all referenced containers for.
|
||||||
*/
|
*/
|
||||||
static void UnloadContainersOfZone(Zone* zone);
|
static void UnloadContainersOfZone(Zone& zone);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Loads all IWDs that can be found in a specified search path.
|
* \brief Loads all IWDs that can be found in a specified search path.
|
||||||
* \param searchPath The search path that contains IWDs to be loaded.
|
* \param searchPath The search path that contains IWDs to be loaded.
|
||||||
*/
|
*/
|
||||||
static void LoadIWDsInSearchPath(ISearchPath* searchPath);
|
static void LoadIWDsInSearchPath(ISearchPath& searchPath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Unloads all IWDs that were loaded from the specified search path.
|
* \brief Unloads all IWDs that were loaded from the specified search path.
|
||||||
* \param searchPath The search path that was used to load the IWDs to be unloaded.
|
* \param searchPath The search path that was used to load the IWDs to be unloaded.
|
||||||
*/
|
*/
|
||||||
static void UnloadIWDsInSearchPath(ISearchPath* searchPath);
|
static void UnloadIWDsInSearchPath(ISearchPath& searchPath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates a \c SearchPaths object containing all IWDs that are currently loaded.
|
* \brief Creates a \c SearchPaths object containing all IWDs that are currently loaded.
|
||||||
@ -47,13 +47,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
static SearchPaths GetIWDSearchPaths();
|
static SearchPaths GetIWDSearchPaths();
|
||||||
|
|
||||||
/**
|
static bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName);
|
||||||
* \brief Loads the obj data for all assets of a zone.
|
static void FinalizeAssetsForZone(AssetLoadingContext& context);
|
||||||
* \param searchPath The search path to use to search for all obj data files.
|
|
||||||
* \param zone The zone of the assets to load the obj data for.
|
|
||||||
*/
|
|
||||||
static void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone);
|
|
||||||
|
|
||||||
static bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName);
|
|
||||||
static void FinalizeAssetsForZone(AssetLoadingContext* context);
|
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "SearchPaths.h"
|
#include "SearchPaths.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
SearchPathOpenFile SearchPaths::Open(const std::string& fileName)
|
SearchPathOpenFile SearchPaths::Open(const std::string& fileName)
|
||||||
@ -38,11 +39,13 @@ void SearchPaths::CommitSearchPath(std::unique_ptr<ISearchPath> searchPath)
|
|||||||
|
|
||||||
void SearchPaths::IncludeSearchPath(ISearchPath* searchPath)
|
void SearchPaths::IncludeSearchPath(ISearchPath* searchPath)
|
||||||
{
|
{
|
||||||
|
assert(searchPath);
|
||||||
m_search_paths.push_back(searchPath);
|
m_search_paths.push_back(searchPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchPaths::RemoveSearchPath(ISearchPath* searchPath)
|
void SearchPaths::RemoveSearchPath(const ISearchPath* searchPath)
|
||||||
{
|
{
|
||||||
|
assert(searchPath);
|
||||||
for (auto i = m_search_paths.begin(); i != m_search_paths.end(); ++i)
|
for (auto i = m_search_paths.begin(); i != m_search_paths.end(); ++i)
|
||||||
{
|
{
|
||||||
if (*i == searchPath)
|
if (*i == searchPath)
|
||||||
|
@ -40,7 +40,7 @@ public:
|
|||||||
* \brief Removes a search path from the \c SearchPaths object. If the search path was committed then it will \b NOT be deleted when destructing the \c
|
* \brief Removes a search path from the \c SearchPaths object. If the search path was committed then it will \b NOT be deleted when destructing the \c
|
||||||
* SearchPaths object. \param searchPath The search path to remove.
|
* SearchPaths object. \param searchPath The search path to remove.
|
||||||
*/
|
*/
|
||||||
void RemoveSearchPath(ISearchPath* searchPath);
|
void RemoveSearchPath(const ISearchPath* searchPath);
|
||||||
|
|
||||||
iterator begin();
|
iterator begin();
|
||||||
iterator end();
|
iterator end();
|
||||||
|
@ -8,9 +8,9 @@ namespace sound_curve
|
|||||||
{
|
{
|
||||||
std::unique_ptr<GenericGraph2D> LoadSoundCurve(const IAssetLoadingManager* manager, const std::string& soundCurveName)
|
std::unique_ptr<GenericGraph2D> LoadSoundCurve(const IAssetLoadingManager* manager, const std::string& soundCurveName)
|
||||||
{
|
{
|
||||||
auto* searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
|
auto& searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
|
||||||
const auto fileName = std::format("soundaliases/{}.vfcurve", soundCurveName);
|
const auto fileName = std::format("soundaliases/{}.vfcurve", soundCurveName);
|
||||||
const auto file = searchPath->Open(fileName);
|
const auto file = searchPath.Open(fileName);
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -9,9 +9,9 @@ namespace
|
|||||||
{
|
{
|
||||||
std::unique_ptr<GenericGraph2D> LoadAccuracyGraph(const IAssetLoadingManager* manager, const std::string& graphName, const std::string& subFolder)
|
std::unique_ptr<GenericGraph2D> LoadAccuracyGraph(const IAssetLoadingManager* manager, const std::string& graphName, const std::string& subFolder)
|
||||||
{
|
{
|
||||||
auto* searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
|
auto& searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
|
||||||
const auto fileName = std::format("accuracy/{}/{}", subFolder, graphName);
|
const auto fileName = std::format("accuracy/{}/{}", subFolder, graphName);
|
||||||
const auto file = searchPath->Open(fileName);
|
const auto file = searchPath.Open(fileName);
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
{
|
{
|
||||||
std::cerr << std::format("Failed to open file for accuracy graph: {}/{}\n", subFolder, graphName);
|
std::cerr << std::format("Failed to open file for accuracy graph: {}/{}\n", subFolder, graphName);
|
||||||
|
@ -20,7 +20,7 @@ bool PartClassificationState::Load(const char** hitLocNames, const size_t hitLoc
|
|||||||
if (ObjLoading::Configuration.Verbose)
|
if (ObjLoading::Configuration.Verbose)
|
||||||
std::cout << "Loading part classification...\n";
|
std::cout << "Loading part classification...\n";
|
||||||
|
|
||||||
const auto file = manager.GetAssetLoadingContext()->m_raw_search_path->Open(PART_CLASSIFICATION_FILE);
|
const auto file = manager.GetAssetLoadingContext()->m_raw_search_path.Open(PART_CLASSIFICATION_FILE);
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
{
|
{
|
||||||
std::cerr << std::format("Could not load part classification: Failed to open {}\n", PART_CLASSIFICATION_FILE);
|
std::cerr << std::format("Could not load part classification: Failed to open {}\n", PART_CLASSIFICATION_FILE);
|
||||||
|
@ -54,7 +54,7 @@ namespace GAME
|
|||||||
XModelLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::set<XAssetInfoGeneric*>& dependencies)
|
XModelLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::set<XAssetInfoGeneric*>& dependencies)
|
||||||
: m_stream(stream),
|
: m_stream(stream),
|
||||||
m_memory(memory),
|
m_memory(memory),
|
||||||
m_script_strings(manager.GetAssetLoadingContext()->m_zone->m_script_strings),
|
m_script_strings(manager.GetAssetLoadingContext()->m_zone.m_script_strings),
|
||||||
m_manager(manager),
|
m_manager(manager),
|
||||||
m_part_classification_state(*m_manager.GetAssetLoadingContext()->GetZoneAssetLoaderState<PartClassificationState>()),
|
m_part_classification_state(*m_manager.GetAssetLoadingContext()->GetZoneAssetLoaderState<PartClassificationState>()),
|
||||||
m_dependencies(dependencies)
|
m_dependencies(dependencies)
|
||||||
@ -616,7 +616,7 @@ namespace GAME
|
|||||||
|
|
||||||
bool LoadLod(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber)
|
bool LoadLod(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber)
|
||||||
{
|
{
|
||||||
const auto file = m_manager.GetAssetLoadingContext()->m_raw_search_path->Open(jLod.file);
|
const auto file = m_manager.GetAssetLoadingContext()->m_raw_search_path.Open(jLod.file);
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
{
|
{
|
||||||
PrintError(xmodel, std::format("Failed to open file for lod {}: \"{}\"", lodNumber, jLod.file));
|
PrintError(xmodel, std::format("Failed to open file for lod {}: \"{}\"", lodNumber, jLod.file));
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "IZoneAssetDumperState.h"
|
#include "IZoneAssetDumperState.h"
|
||||||
#include "Obj/Gdt/GdtStream.h"
|
#include "Obj/Gdt/GdtStream.h"
|
||||||
|
#include "SearchPath/ISearchPath.h"
|
||||||
#include "Utils/ClassUtils.h"
|
#include "Utils/ClassUtils.h"
|
||||||
#include "Zone/Zone.h"
|
#include "Zone/Zone.h"
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ public:
|
|||||||
Zone* m_zone;
|
Zone* m_zone;
|
||||||
std::string m_base_path;
|
std::string m_base_path;
|
||||||
std::unique_ptr<GdtOutputStream> m_gdt;
|
std::unique_ptr<GdtOutputStream> m_gdt;
|
||||||
|
ISearchPath* m_obj_search_path;
|
||||||
|
|
||||||
AssetDumpingContext();
|
AssetDumpingContext();
|
||||||
|
|
||||||
|
@ -1,13 +1,63 @@
|
|||||||
#include "AssetDumperGfxImage.h"
|
#include "AssetDumperGfxImage.h"
|
||||||
|
|
||||||
#include "Image/DdsWriter.h"
|
#include "Image/DdsWriter.h"
|
||||||
|
#include "Image/Dx9TextureLoader.h"
|
||||||
|
#include "Image/IwiLoader.h"
|
||||||
|
#include "Image/IwiTypes.h"
|
||||||
#include "Image/IwiWriter6.h"
|
#include "Image/IwiWriter6.h"
|
||||||
|
#include "Image/Texture.h"
|
||||||
#include "ObjWriting.h"
|
#include "ObjWriting.h"
|
||||||
|
#include "SearchPath/ISearchPath.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
using namespace IW3;
|
using namespace IW3;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::unique_ptr<Texture> LoadImageFromLoadDef(const GfxImage* image)
|
||||||
|
{
|
||||||
|
Dx9TextureLoader textureLoader;
|
||||||
|
|
||||||
|
const auto& loadDef = *image->texture.loadDef;
|
||||||
|
textureLoader.Width(loadDef.dimensions[0]).Height(loadDef.dimensions[1]).Depth(loadDef.dimensions[2]);
|
||||||
|
|
||||||
|
if (loadDef.flags & iwi6::IMG_FLAG_VOLMAP)
|
||||||
|
textureLoader.Type(TextureType::T_3D);
|
||||||
|
else if (loadDef.flags & iwi6::IMG_FLAG_CUBEMAP)
|
||||||
|
textureLoader.Type(TextureType::T_CUBE);
|
||||||
|
else
|
||||||
|
textureLoader.Type(TextureType::T_2D);
|
||||||
|
|
||||||
|
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format));
|
||||||
|
textureLoader.HasMipMaps(!(loadDef.flags & iwi6::IMG_FLAG_NOMIPMAPS));
|
||||||
|
return textureLoader.LoadTexture(loadDef.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageFromIwi(const GfxImage* image, ISearchPath* searchPath)
|
||||||
|
{
|
||||||
|
const auto imageFileName = std::format("images/{}.iwi", image->name);
|
||||||
|
const auto filePathImage = searchPath->Open(imageFileName);
|
||||||
|
if (!filePathImage.IsOpen())
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Could not find data for image \"{}\"\n", image->name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iwi::LoadIwi(*filePathImage.m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageData(ISearchPath* searchPath, const GfxImage* image)
|
||||||
|
{
|
||||||
|
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
||||||
|
return LoadImageFromLoadDef(image);
|
||||||
|
|
||||||
|
return LoadImageFromIwi(image, searchPath);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
AssetDumperGfxImage::AssetDumperGfxImage()
|
AssetDumperGfxImage::AssetDumperGfxImage()
|
||||||
{
|
{
|
||||||
switch (ObjWriting::Configuration.ImageOutputFormat)
|
switch (ObjWriting::Configuration.ImageOutputFormat)
|
||||||
@ -27,37 +77,29 @@ AssetDumperGfxImage::AssetDumperGfxImage()
|
|||||||
|
|
||||||
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
return true;
|
||||||
return image->cardMemory.platform[0] > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AssetDumperGfxImage::GetAssetFileName(XAssetInfo<GfxImage>* asset) const
|
std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo<GfxImage>& asset) const
|
||||||
{
|
{
|
||||||
std::string cleanAssetName = asset->m_name;
|
auto cleanAssetName = asset.m_name;
|
||||||
for (auto& c : cleanAssetName)
|
std::ranges::replace(cleanAssetName, '*', '_');
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '*':
|
|
||||||
c = '_';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension());
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "images/" + cleanAssetName + m_writer->GetFileExtension();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
const auto* image = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetAssetFileName(asset));
|
const auto texture = LoadImageData(context.m_obj_search_path, image);
|
||||||
|
if (!texture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset));
|
||||||
|
|
||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& stream = *assetFile;
|
auto& stream = *assetFile;
|
||||||
m_writer->DumpImage(stream, image->texture.texture);
|
m_writer->DumpImage(stream, texture.get());
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace IW3
|
|||||||
{
|
{
|
||||||
std::unique_ptr<IImageWriter> m_writer;
|
std::unique_ptr<IImageWriter> m_writer;
|
||||||
|
|
||||||
std::string GetAssetFileName(XAssetInfo<GfxImage>* asset) const;
|
[[nodiscard]] std::string GetAssetFileName(const XAssetInfo<GfxImage>& asset) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
||||||
|
@ -1,13 +1,60 @@
|
|||||||
#include "AssetDumperGfxImage.h"
|
#include "AssetDumperGfxImage.h"
|
||||||
|
|
||||||
#include "Image/DdsWriter.h"
|
#include "Image/DdsWriter.h"
|
||||||
|
#include "Image/Dx9TextureLoader.h"
|
||||||
|
#include "Image/IwiLoader.h"
|
||||||
#include "Image/IwiWriter8.h"
|
#include "Image/IwiWriter8.h"
|
||||||
#include "ObjWriting.h"
|
#include "ObjWriting.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::unique_ptr<Texture> LoadImageFromLoadDef(const GfxImage* image)
|
||||||
|
{
|
||||||
|
Dx9TextureLoader textureLoader;
|
||||||
|
|
||||||
|
const auto& loadDef = *image->texture.loadDef;
|
||||||
|
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
|
||||||
|
|
||||||
|
if ((loadDef.flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_3D)
|
||||||
|
textureLoader.Type(TextureType::T_3D);
|
||||||
|
else if ((loadDef.flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_CUBE)
|
||||||
|
textureLoader.Type(TextureType::T_CUBE);
|
||||||
|
else
|
||||||
|
textureLoader.Type(TextureType::T_2D);
|
||||||
|
|
||||||
|
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format));
|
||||||
|
textureLoader.HasMipMaps(!(loadDef.flags & iwi8::IMG_FLAG_NOMIPMAPS));
|
||||||
|
return textureLoader.LoadTexture(loadDef.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageFromIwi(const GfxImage* image, ISearchPath* searchPath)
|
||||||
|
{
|
||||||
|
const auto imageFileName = std::format("images/{}.iwi", image->name);
|
||||||
|
const auto filePathImage = searchPath->Open(imageFileName);
|
||||||
|
if (!filePathImage.IsOpen())
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Could not find data for image \"{}\"\n", image->name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iwi::LoadIwi(*filePathImage.m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageData(ISearchPath* searchPath, const GfxImage* image)
|
||||||
|
{
|
||||||
|
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
||||||
|
return LoadImageFromLoadDef(image);
|
||||||
|
|
||||||
|
return LoadImageFromIwi(image, searchPath);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
AssetDumperGfxImage::AssetDumperGfxImage()
|
AssetDumperGfxImage::AssetDumperGfxImage()
|
||||||
{
|
{
|
||||||
switch (ObjWriting::Configuration.ImageOutputFormat)
|
switch (ObjWriting::Configuration.ImageOutputFormat)
|
||||||
@ -27,37 +74,29 @@ AssetDumperGfxImage::AssetDumperGfxImage()
|
|||||||
|
|
||||||
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
return true;
|
||||||
return image->cardMemory.platform[0] > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AssetDumperGfxImage::GetAssetFileName(XAssetInfo<GfxImage>* asset) const
|
std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo<GfxImage>& asset) const
|
||||||
{
|
{
|
||||||
std::string cleanAssetName = asset->m_name;
|
auto cleanAssetName = asset.m_name;
|
||||||
for (auto& c : cleanAssetName)
|
std::ranges::replace(cleanAssetName, '*', '_');
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '*':
|
|
||||||
c = '_';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension());
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "images/" + cleanAssetName + m_writer->GetFileExtension();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
const auto* image = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetAssetFileName(asset));
|
const auto texture = LoadImageData(context.m_obj_search_path, image);
|
||||||
|
if (!texture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset));
|
||||||
|
|
||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& stream = *assetFile;
|
auto& stream = *assetFile;
|
||||||
m_writer->DumpImage(stream, image->texture.texture);
|
m_writer->DumpImage(stream, texture.get());
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace IW4
|
|||||||
{
|
{
|
||||||
std::unique_ptr<IImageWriter> m_writer;
|
std::unique_ptr<IImageWriter> m_writer;
|
||||||
|
|
||||||
std::string GetAssetFileName(XAssetInfo<GfxImage>* asset) const;
|
[[nodiscard]] std::string GetAssetFileName(const XAssetInfo<GfxImage>& asset) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
||||||
|
@ -1,13 +1,61 @@
|
|||||||
#include "AssetDumperGfxImage.h"
|
#include "AssetDumperGfxImage.h"
|
||||||
|
|
||||||
#include "Image/DdsWriter.h"
|
#include "Image/DdsWriter.h"
|
||||||
|
#include "Image/Dx9TextureLoader.h"
|
||||||
|
#include "Image/IwiLoader.h"
|
||||||
#include "Image/IwiWriter8.h"
|
#include "Image/IwiWriter8.h"
|
||||||
#include "ObjWriting.h"
|
#include "ObjWriting.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
using namespace IW5;
|
using namespace IW5;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::unique_ptr<Texture> LoadImageFromLoadDef(const GfxImage* image)
|
||||||
|
{
|
||||||
|
Dx9TextureLoader textureLoader;
|
||||||
|
|
||||||
|
const auto& loadDef = *image->texture.loadDef;
|
||||||
|
|
||||||
|
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
|
||||||
|
|
||||||
|
if ((loadDef.flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_3D)
|
||||||
|
textureLoader.Type(TextureType::T_3D);
|
||||||
|
else if ((loadDef.flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_CUBE)
|
||||||
|
textureLoader.Type(TextureType::T_CUBE);
|
||||||
|
else
|
||||||
|
textureLoader.Type(TextureType::T_2D);
|
||||||
|
|
||||||
|
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format));
|
||||||
|
textureLoader.HasMipMaps(!(loadDef.flags & iwi8::IMG_FLAG_NOMIPMAPS));
|
||||||
|
return textureLoader.LoadTexture(loadDef.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageFromIwi(const GfxImage* image, ISearchPath* searchPath)
|
||||||
|
{
|
||||||
|
const auto imageFileName = std::format("images/{}.iwi", image->name);
|
||||||
|
const auto filePathImage = searchPath->Open(imageFileName);
|
||||||
|
if (!filePathImage.IsOpen())
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Could not find data for image \"{}\"\n", image->name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iwi::LoadIwi(*filePathImage.m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageData(ISearchPath* searchPath, const GfxImage* image)
|
||||||
|
{
|
||||||
|
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
||||||
|
return LoadImageFromLoadDef(image);
|
||||||
|
|
||||||
|
return LoadImageFromIwi(image, searchPath);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
AssetDumperGfxImage::AssetDumperGfxImage()
|
AssetDumperGfxImage::AssetDumperGfxImage()
|
||||||
{
|
{
|
||||||
switch (ObjWriting::Configuration.ImageOutputFormat)
|
switch (ObjWriting::Configuration.ImageOutputFormat)
|
||||||
@ -27,37 +75,29 @@ AssetDumperGfxImage::AssetDumperGfxImage()
|
|||||||
|
|
||||||
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
return true;
|
||||||
return image->cardMemory.platform[0] > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AssetDumperGfxImage::GetAssetFileName(XAssetInfo<GfxImage>* asset) const
|
std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo<GfxImage>& asset) const
|
||||||
{
|
{
|
||||||
std::string cleanAssetName = asset->m_name;
|
auto cleanAssetName = asset.m_name;
|
||||||
for (auto& c : cleanAssetName)
|
std::ranges::replace(cleanAssetName, '*', '_');
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '*':
|
|
||||||
c = '_';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension());
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "images/" + cleanAssetName + m_writer->GetFileExtension();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
const auto* image = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetAssetFileName(asset));
|
const auto texture = LoadImageData(context.m_obj_search_path, image);
|
||||||
|
if (!texture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset));
|
||||||
|
|
||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& stream = *assetFile;
|
auto& stream = *assetFile;
|
||||||
m_writer->DumpImage(stream, image->texture.texture);
|
m_writer->DumpImage(stream, texture.get());
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace IW5
|
|||||||
{
|
{
|
||||||
std::unique_ptr<IImageWriter> m_writer;
|
std::unique_ptr<IImageWriter> m_writer;
|
||||||
|
|
||||||
std::string GetAssetFileName(XAssetInfo<GfxImage>* asset) const;
|
[[nodiscard]] std::string GetAssetFileName(const XAssetInfo<GfxImage>& asset) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
||||||
|
@ -1,13 +1,60 @@
|
|||||||
#include "AssetDumperGfxImage.h"
|
#include "AssetDumperGfxImage.h"
|
||||||
|
|
||||||
#include "Image/DdsWriter.h"
|
#include "Image/DdsWriter.h"
|
||||||
#include "Image/IwiWriter27.h"
|
#include "Image/Dx9TextureLoader.h"
|
||||||
|
#include "Image/IwiLoader.h"
|
||||||
|
#include "Image/IwiWriter13.h"
|
||||||
#include "ObjWriting.h"
|
#include "ObjWriting.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
using namespace T5;
|
using namespace T5;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::unique_ptr<Texture> LoadImageFromLoadDef(const GfxImage* image)
|
||||||
|
{
|
||||||
|
Dx9TextureLoader textureLoader;
|
||||||
|
|
||||||
|
const auto& loadDef = *image->texture.loadDef;
|
||||||
|
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
|
||||||
|
|
||||||
|
if (loadDef.flags & iwi13::IMG_FLAG_VOLMAP)
|
||||||
|
textureLoader.Type(TextureType::T_3D);
|
||||||
|
else if (loadDef.flags & iwi13::IMG_FLAG_CUBEMAP)
|
||||||
|
textureLoader.Type(TextureType::T_CUBE);
|
||||||
|
else
|
||||||
|
textureLoader.Type(TextureType::T_2D);
|
||||||
|
|
||||||
|
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format));
|
||||||
|
textureLoader.HasMipMaps(!(loadDef.flags & iwi13::IMG_FLAG_NOMIPMAPS));
|
||||||
|
return textureLoader.LoadTexture(loadDef.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageFromIwi(const GfxImage* image, ISearchPath* searchPath)
|
||||||
|
{
|
||||||
|
const auto imageFileName = std::format("images/{}.iwi", image->name);
|
||||||
|
const auto filePathImage = searchPath->Open(imageFileName);
|
||||||
|
if (!filePathImage.IsOpen())
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Could not find data for image \"{}\"\n", image->name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iwi::LoadIwi(*filePathImage.m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageData(ISearchPath* searchPath, const GfxImage* image)
|
||||||
|
{
|
||||||
|
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
||||||
|
return LoadImageFromLoadDef(image);
|
||||||
|
|
||||||
|
return LoadImageFromIwi(image, searchPath);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
AssetDumperGfxImage::AssetDumperGfxImage()
|
AssetDumperGfxImage::AssetDumperGfxImage()
|
||||||
{
|
{
|
||||||
switch (ObjWriting::Configuration.ImageOutputFormat)
|
switch (ObjWriting::Configuration.ImageOutputFormat)
|
||||||
@ -16,7 +63,7 @@ AssetDumperGfxImage::AssetDumperGfxImage()
|
|||||||
m_writer = std::make_unique<DdsWriter>();
|
m_writer = std::make_unique<DdsWriter>();
|
||||||
break;
|
break;
|
||||||
case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI:
|
case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI:
|
||||||
m_writer = std::make_unique<iwi27::IwiWriter>();
|
m_writer = std::make_unique<iwi13::IwiWriter>();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
@ -27,37 +74,29 @@ AssetDumperGfxImage::AssetDumperGfxImage()
|
|||||||
|
|
||||||
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
return true;
|
||||||
return image->loadedSize > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AssetDumperGfxImage::GetAssetFileName(XAssetInfo<GfxImage>* asset) const
|
std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo<GfxImage>& asset) const
|
||||||
{
|
{
|
||||||
std::string cleanAssetName = asset->m_name;
|
auto cleanAssetName = asset.m_name;
|
||||||
for (auto& c : cleanAssetName)
|
std::ranges::replace(cleanAssetName, '*', '_');
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '*':
|
|
||||||
c = '_';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension());
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "images/" + cleanAssetName + m_writer->GetFileExtension();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
const auto* image = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetAssetFileName(asset));
|
const auto texture = LoadImageData(context.m_obj_search_path, image);
|
||||||
|
if (!texture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset));
|
||||||
|
|
||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& stream = *assetFile;
|
auto& stream = *assetFile;
|
||||||
m_writer->DumpImage(stream, image->texture.texture);
|
m_writer->DumpImage(stream, texture.get());
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace T5
|
|||||||
{
|
{
|
||||||
std::unique_ptr<IImageWriter> m_writer;
|
std::unique_ptr<IImageWriter> m_writer;
|
||||||
|
|
||||||
std::string GetAssetFileName(XAssetInfo<GfxImage>* asset) const;
|
[[nodiscard]] std::string GetAssetFileName(const XAssetInfo<GfxImage>& asset) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
||||||
|
@ -1,13 +1,78 @@
|
|||||||
#include "AssetDumperGfxImage.h"
|
#include "AssetDumperGfxImage.h"
|
||||||
|
|
||||||
#include "Image/DdsWriter.h"
|
#include "Image/DdsWriter.h"
|
||||||
|
#include "Image/Dx12TextureLoader.h"
|
||||||
|
#include "Image/IwiLoader.h"
|
||||||
#include "Image/IwiWriter27.h"
|
#include "Image/IwiWriter27.h"
|
||||||
|
#include "ObjContainer/IPak/IPak.h"
|
||||||
#include "ObjWriting.h"
|
#include "ObjWriting.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
using namespace T6;
|
using namespace T6;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::unique_ptr<Texture> LoadImageFromLoadDef(const GfxImage* image)
|
||||||
|
{
|
||||||
|
Dx12TextureLoader textureLoader;
|
||||||
|
|
||||||
|
const auto& loadDef = *image->texture.loadDef;
|
||||||
|
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
|
||||||
|
|
||||||
|
if (loadDef.flags & iwi27::IMG_FLAG_VOLMAP)
|
||||||
|
textureLoader.Type(TextureType::T_3D);
|
||||||
|
else if (loadDef.flags & iwi27::IMG_FLAG_CUBEMAP)
|
||||||
|
textureLoader.Type(TextureType::T_CUBE);
|
||||||
|
else
|
||||||
|
textureLoader.Type(TextureType::T_2D);
|
||||||
|
|
||||||
|
textureLoader.Format(static_cast<oat::DXGI_FORMAT>(loadDef.format));
|
||||||
|
textureLoader.HasMipMaps(!(loadDef.flags & iwi27::IMG_FLAG_NOMIPMAPS));
|
||||||
|
return textureLoader.LoadTexture(loadDef.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageFromIwi(const GfxImage* image, ISearchPath* searchPath)
|
||||||
|
{
|
||||||
|
if (image->streamedPartCount > 0)
|
||||||
|
{
|
||||||
|
for (auto* ipak : IPak::Repository)
|
||||||
|
{
|
||||||
|
auto ipakStream = ipak->GetEntryStream(image->hash, image->streamedParts[0].hash);
|
||||||
|
|
||||||
|
if (ipakStream)
|
||||||
|
{
|
||||||
|
auto loadedTexture = iwi::LoadIwi(*ipakStream);
|
||||||
|
ipakStream->close();
|
||||||
|
|
||||||
|
if (loadedTexture != nullptr)
|
||||||
|
return loadedTexture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto imageFileName = std::format("images/{}.iwi", image->name);
|
||||||
|
const auto filePathImage = searchPath->Open(imageFileName);
|
||||||
|
if (!filePathImage.IsOpen())
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Could not find data for image \"{}\"\n", image->name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iwi::LoadIwi(*filePathImage.m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> LoadImageData(ISearchPath* searchPath, const GfxImage* image)
|
||||||
|
{
|
||||||
|
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
|
||||||
|
return LoadImageFromLoadDef(image);
|
||||||
|
|
||||||
|
return LoadImageFromIwi(image, searchPath);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
AssetDumperGfxImage::AssetDumperGfxImage()
|
AssetDumperGfxImage::AssetDumperGfxImage()
|
||||||
{
|
{
|
||||||
switch (ObjWriting::Configuration.ImageOutputFormat)
|
switch (ObjWriting::Configuration.ImageOutputFormat)
|
||||||
@ -27,37 +92,29 @@ AssetDumperGfxImage::AssetDumperGfxImage()
|
|||||||
|
|
||||||
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
bool AssetDumperGfxImage::ShouldDump(XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
return true;
|
||||||
return image->loadedSize > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AssetDumperGfxImage::GetAssetFileName(XAssetInfo<GfxImage>* asset) const
|
std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo<GfxImage>& asset) const
|
||||||
{
|
{
|
||||||
std::string cleanAssetName = asset->m_name;
|
auto cleanAssetName = asset.m_name;
|
||||||
for (auto& c : cleanAssetName)
|
std::ranges::replace(cleanAssetName, '*', '_');
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '*':
|
|
||||||
c = '_';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension());
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "images/" + cleanAssetName + m_writer->GetFileExtension();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
|
||||||
{
|
{
|
||||||
const auto* image = asset->Asset();
|
const auto* image = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetAssetFileName(asset));
|
const auto texture = LoadImageData(context.m_obj_search_path, image);
|
||||||
|
if (!texture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset));
|
||||||
|
|
||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& stream = *assetFile;
|
auto& stream = *assetFile;
|
||||||
m_writer->DumpImage(stream, image->texture.texture);
|
m_writer->DumpImage(stream, texture.get());
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace T6
|
|||||||
{
|
{
|
||||||
std::unique_ptr<IImageWriter> m_writer;
|
std::unique_ptr<IImageWriter> m_writer;
|
||||||
|
|
||||||
std::string GetAssetFileName(XAssetInfo<GfxImage>* asset) const;
|
std::string GetAssetFileName(const XAssetInfo<GfxImage>& asset) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
bool ShouldDump(XAssetInfo<GfxImage>* asset) override;
|
||||||
|
@ -13,10 +13,51 @@ const std::map<ImageFormatId, ImageFormatId> DDS_CONVERSION_TABLE{
|
|||||||
|
|
||||||
class DdsWriterInternal
|
class DdsWriterInternal
|
||||||
{
|
{
|
||||||
std::ostream& m_stream;
|
public:
|
||||||
Texture* m_texture;
|
static bool SupportsImageFormat(const ImageFormat* imageFormat)
|
||||||
std::unique_ptr<Texture> m_converted_texture;
|
{
|
||||||
bool m_use_dx10_extension;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string GetFileExtension()
|
||||||
|
{
|
||||||
|
return ".dds";
|
||||||
|
}
|
||||||
|
|
||||||
|
DdsWriterInternal(std::ostream& stream, const Texture* texture)
|
||||||
|
: m_stream(stream),
|
||||||
|
m_texture(texture),
|
||||||
|
m_use_dx10_extension(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpImage()
|
||||||
|
{
|
||||||
|
ConvertTextureIfNecessary();
|
||||||
|
|
||||||
|
DDS_HEADER header{};
|
||||||
|
PopulateDdsHeader(header);
|
||||||
|
|
||||||
|
constexpr auto magic = MakeFourCc('D', 'D', 'S', ' ');
|
||||||
|
|
||||||
|
m_stream.write(reinterpret_cast<const char*>(&magic), sizeof(magic));
|
||||||
|
m_stream.write(reinterpret_cast<const char*>(&header), sizeof(header));
|
||||||
|
|
||||||
|
if (m_use_dx10_extension)
|
||||||
|
{
|
||||||
|
DDS_HEADER_DXT10 dxt10{};
|
||||||
|
PopulateDxt10Header(dxt10);
|
||||||
|
m_stream.write(reinterpret_cast<const char*>(&dxt10), sizeof(dxt10));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto mipCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1;
|
||||||
|
for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++)
|
||||||
|
{
|
||||||
|
const auto* buffer = m_texture->GetBufferForMipLevel(mipLevel);
|
||||||
|
const auto mipLevelSize = m_texture->GetSizeOfMipLevel(mipLevel) * m_texture->GetFaceCount();
|
||||||
|
m_stream.write(reinterpret_cast<const char*>(buffer), mipLevelSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr unsigned Mask1(const unsigned length)
|
static constexpr unsigned Mask1(const unsigned length)
|
||||||
{
|
{
|
||||||
@ -164,61 +205,20 @@ class DdsWriterInternal
|
|||||||
|
|
||||||
void ConvertTextureIfNecessary()
|
void ConvertTextureIfNecessary()
|
||||||
{
|
{
|
||||||
auto entry = DDS_CONVERSION_TABLE.find(m_texture->GetFormat()->GetId());
|
const auto entry = DDS_CONVERSION_TABLE.find(m_texture->GetFormat()->GetId());
|
||||||
|
|
||||||
if (entry != DDS_CONVERSION_TABLE.end())
|
if (entry != DDS_CONVERSION_TABLE.end())
|
||||||
{
|
{
|
||||||
TextureConverter converter(m_texture, ImageFormat::ALL_FORMATS[static_cast<unsigned>(entry->second)]);
|
TextureConverter converter(m_texture, ImageFormat::ALL_FORMATS[static_cast<unsigned>(entry->second)]);
|
||||||
m_converted_texture = std::unique_ptr<Texture>(converter.Convert());
|
m_converted_texture = converter.Convert();
|
||||||
m_texture = m_converted_texture.get();
|
m_texture = m_converted_texture.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
std::ostream& m_stream;
|
||||||
static bool SupportsImageFormat(const ImageFormat* imageFormat)
|
const Texture* m_texture;
|
||||||
{
|
std::unique_ptr<Texture> m_converted_texture;
|
||||||
return true;
|
bool m_use_dx10_extension;
|
||||||
}
|
|
||||||
|
|
||||||
static std::string GetFileExtension()
|
|
||||||
{
|
|
||||||
return ".dds";
|
|
||||||
}
|
|
||||||
|
|
||||||
DdsWriterInternal(std::ostream& stream, Texture* texture)
|
|
||||||
: m_stream(stream),
|
|
||||||
m_texture(texture),
|
|
||||||
m_use_dx10_extension(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DumpImage()
|
|
||||||
{
|
|
||||||
ConvertTextureIfNecessary();
|
|
||||||
|
|
||||||
DDS_HEADER header{};
|
|
||||||
PopulateDdsHeader(header);
|
|
||||||
|
|
||||||
constexpr auto magic = MakeFourCc('D', 'D', 'S', ' ');
|
|
||||||
|
|
||||||
m_stream.write(reinterpret_cast<const char*>(&magic), sizeof(magic));
|
|
||||||
m_stream.write(reinterpret_cast<const char*>(&header), sizeof(header));
|
|
||||||
|
|
||||||
if (m_use_dx10_extension)
|
|
||||||
{
|
|
||||||
DDS_HEADER_DXT10 dxt10{};
|
|
||||||
PopulateDxt10Header(dxt10);
|
|
||||||
m_stream.write(reinterpret_cast<const char*>(&dxt10), sizeof(dxt10));
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto mipCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1;
|
|
||||||
for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++)
|
|
||||||
{
|
|
||||||
const auto* buffer = m_texture->GetBufferForMipLevel(mipLevel);
|
|
||||||
const auto mipLevelSize = m_texture->GetSizeOfMipLevel(mipLevel) * m_texture->GetFaceCount();
|
|
||||||
m_stream.write(reinterpret_cast<const char*>(buffer), mipLevelSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DdsWriter::~DdsWriter() = default;
|
DdsWriter::~DdsWriter() = default;
|
||||||
@ -233,7 +233,7 @@ std::string DdsWriter::GetFileExtension()
|
|||||||
return DdsWriterInternal::GetFileExtension();
|
return DdsWriterInternal::GetFileExtension();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DdsWriter::DumpImage(std::ostream& stream, Texture* texture)
|
void DdsWriter::DumpImage(std::ostream& stream, const Texture* texture)
|
||||||
{
|
{
|
||||||
DdsWriterInternal internal(stream, texture);
|
DdsWriterInternal internal(stream, texture);
|
||||||
internal.DumpImage();
|
internal.DumpImage();
|
||||||
|
@ -8,5 +8,5 @@ public:
|
|||||||
|
|
||||||
bool SupportsImageFormat(const ImageFormat* imageFormat) override;
|
bool SupportsImageFormat(const ImageFormat* imageFormat) override;
|
||||||
std::string GetFileExtension() override;
|
std::string GetFileExtension() override;
|
||||||
void DumpImage(std::ostream& stream, Texture* texture) override;
|
void DumpImage(std::ostream& stream, const Texture* texture) override;
|
||||||
};
|
};
|
||||||
|
@ -8,9 +8,14 @@
|
|||||||
class IImageWriter
|
class IImageWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
IImageWriter() = default;
|
||||||
virtual ~IImageWriter() = default;
|
virtual ~IImageWriter() = default;
|
||||||
|
IImageWriter(const IImageWriter& other) = default;
|
||||||
|
IImageWriter(IImageWriter&& other) noexcept = default;
|
||||||
|
IImageWriter& operator=(const IImageWriter& other) = default;
|
||||||
|
IImageWriter& operator=(IImageWriter&& other) noexcept = default;
|
||||||
|
|
||||||
virtual bool SupportsImageFormat(const ImageFormat* imageFormat) = 0;
|
virtual bool SupportsImageFormat(const ImageFormat* imageFormat) = 0;
|
||||||
virtual std::string GetFileExtension() = 0;
|
virtual std::string GetFileExtension() = 0;
|
||||||
virtual void DumpImage(std::ostream& stream, Texture* texture) = 0;
|
virtual void DumpImage(std::ostream& stream, const Texture* texture) = 0;
|
||||||
};
|
};
|
||||||
|
141
src/ObjWriting/Image/IwiWriter13.cpp
Normal file
141
src/ObjWriting/Image/IwiWriter13.cpp
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#include "IwiWriter13.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
using namespace iwi13;
|
||||||
|
|
||||||
|
IwiWriter::IwiWriter() = default;
|
||||||
|
|
||||||
|
IwiWriter::~IwiWriter() = default;
|
||||||
|
|
||||||
|
IwiFormat IwiWriter::GetIwiFormatForImageFormat(const ImageFormat* imageFormat)
|
||||||
|
{
|
||||||
|
switch (imageFormat->GetId())
|
||||||
|
{
|
||||||
|
case ImageFormatId::R8_G8_B8:
|
||||||
|
return IwiFormat::IMG_FORMAT_BITMAP_RGB;
|
||||||
|
|
||||||
|
case ImageFormatId::R8_G8_B8_A8:
|
||||||
|
return IwiFormat::IMG_FORMAT_BITMAP_RGBA;
|
||||||
|
|
||||||
|
case ImageFormatId::A8:
|
||||||
|
return IwiFormat::IMG_FORMAT_BITMAP_ALPHA;
|
||||||
|
|
||||||
|
case ImageFormatId::R16_G16_B16_A16_FLOAT:
|
||||||
|
return IwiFormat::IMG_FORMAT_A16B16G16R16F;
|
||||||
|
|
||||||
|
case ImageFormatId::BC1:
|
||||||
|
return IwiFormat::IMG_FORMAT_DXT1;
|
||||||
|
|
||||||
|
case ImageFormatId::BC2:
|
||||||
|
return IwiFormat::IMG_FORMAT_DXT3;
|
||||||
|
|
||||||
|
case ImageFormatId::BC3:
|
||||||
|
return IwiFormat::IMG_FORMAT_DXT5;
|
||||||
|
|
||||||
|
case ImageFormatId::BC5:
|
||||||
|
return IwiFormat::IMG_FORMAT_DXN;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return IwiFormat::IMG_FORMAT_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IwiWriter::SupportsImageFormat(const ImageFormat* imageFormat)
|
||||||
|
{
|
||||||
|
return GetIwiFormatForImageFormat(imageFormat) != IwiFormat::IMG_FORMAT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string IwiWriter::GetFileExtension()
|
||||||
|
{
|
||||||
|
return ".iwi";
|
||||||
|
}
|
||||||
|
|
||||||
|
void IwiWriter::WriteVersion(std::ostream& stream)
|
||||||
|
{
|
||||||
|
IwiVersion version{};
|
||||||
|
version.tag[0] = 'I';
|
||||||
|
version.tag[1] = 'W';
|
||||||
|
version.tag[2] = 'i';
|
||||||
|
version.version = 13;
|
||||||
|
|
||||||
|
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture)
|
||||||
|
{
|
||||||
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
|
header.dimensions[2] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IwiWriter::FillHeaderCube(IwiHeader& header, const TextureCube& texture)
|
||||||
|
{
|
||||||
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
|
header.dimensions[2] = 1;
|
||||||
|
header.flags |= IMG_FLAG_CUBEMAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IwiWriter::FillHeader3D(IwiHeader& header, const Texture3D& texture)
|
||||||
|
{
|
||||||
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
|
header.dimensions[2] = static_cast<uint16_t>(texture.GetDepth());
|
||||||
|
header.flags |= IMG_FLAG_VOLMAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IwiWriter::DumpImage(std::ostream& stream, const Texture* texture)
|
||||||
|
{
|
||||||
|
assert(texture != nullptr);
|
||||||
|
|
||||||
|
WriteVersion(stream);
|
||||||
|
|
||||||
|
IwiHeader header{};
|
||||||
|
header.flags = 0;
|
||||||
|
header.gamma = 0.0f;
|
||||||
|
|
||||||
|
header.format = static_cast<int8_t>(GetIwiFormatForImageFormat(texture->GetFormat()));
|
||||||
|
|
||||||
|
if (!texture->HasMipMaps())
|
||||||
|
header.flags |= IMG_FLAG_NOMIPMAPS;
|
||||||
|
|
||||||
|
auto currentFileSize = sizeof(IwiVersion) + sizeof(IwiHeader);
|
||||||
|
|
||||||
|
const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1;
|
||||||
|
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)
|
||||||
|
{
|
||||||
|
const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
|
||||||
|
currentFileSize += mipLevelSize;
|
||||||
|
|
||||||
|
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(IwiHeader::fileSizeForPicmip)>))
|
||||||
|
header.fileSizeForPicmip[currentMipLevel] = currentFileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto* texture2D = dynamic_cast<const Texture2D*>(texture))
|
||||||
|
{
|
||||||
|
FillHeader2D(header, *texture2D);
|
||||||
|
}
|
||||||
|
else if (const auto* textureCube = dynamic_cast<const TextureCube*>(texture))
|
||||||
|
{
|
||||||
|
FillHeaderCube(header, *textureCube);
|
||||||
|
}
|
||||||
|
else if (const auto* texture3D = dynamic_cast<const Texture3D*>(texture))
|
||||||
|
{
|
||||||
|
FillHeader3D(header, *texture3D);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.write(reinterpret_cast<char*>(&header), sizeof(IwiHeader));
|
||||||
|
|
||||||
|
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)
|
||||||
|
{
|
||||||
|
const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
|
||||||
|
stream.write(reinterpret_cast<const char*>(texture->GetBufferForMipLevel(currentMipLevel)), mipLevelSize);
|
||||||
|
}
|
||||||
|
}
|
30
src/ObjWriting/Image/IwiWriter13.h
Normal file
30
src/ObjWriting/Image/IwiWriter13.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IImageWriter.h"
|
||||||
|
#include "Image/IwiTypes.h"
|
||||||
|
|
||||||
|
namespace iwi13
|
||||||
|
{
|
||||||
|
class IwiWriter final : public IImageWriter
|
||||||
|
{
|
||||||
|
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
|
||||||
|
|
||||||
|
static void WriteVersion(std::ostream& stream);
|
||||||
|
static void FillHeader2D(IwiHeader& header, const Texture2D& texture);
|
||||||
|
static void FillHeaderCube(IwiHeader& header, const TextureCube& texture);
|
||||||
|
static void FillHeader3D(IwiHeader& header, const Texture3D& texture);
|
||||||
|
|
||||||
|
public:
|
||||||
|
IwiWriter();
|
||||||
|
IwiWriter(const IwiWriter& other) = delete;
|
||||||
|
IwiWriter(IwiWriter&& other) noexcept = delete;
|
||||||
|
~IwiWriter() override;
|
||||||
|
|
||||||
|
IwiWriter& operator=(const IwiWriter& other) = delete;
|
||||||
|
IwiWriter& operator=(IwiWriter&& other) noexcept = delete;
|
||||||
|
|
||||||
|
bool SupportsImageFormat(const ImageFormat* imageFormat) override;
|
||||||
|
std::string GetFileExtension() override;
|
||||||
|
void DumpImage(std::ostream& stream, const Texture* texture) override;
|
||||||
|
};
|
||||||
|
} // namespace iwi13
|
@ -63,30 +63,30 @@ void IwiWriter::WriteVersion(std::ostream& stream)
|
|||||||
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion));
|
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::FillHeader2D(IwiHeader* header, Texture2D* texture)
|
void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture)
|
||||||
{
|
{
|
||||||
header->dimensions[0] = static_cast<uint16_t>(texture->GetWidth());
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
header->dimensions[1] = static_cast<uint16_t>(texture->GetHeight());
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
header->dimensions[2] = 1;
|
header.dimensions[2] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::FillHeaderCube(IwiHeader* header, TextureCube* texture)
|
void IwiWriter::FillHeaderCube(IwiHeader& header, const TextureCube& texture)
|
||||||
{
|
{
|
||||||
header->dimensions[0] = static_cast<uint16_t>(texture->GetWidth());
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
header->dimensions[1] = static_cast<uint16_t>(texture->GetHeight());
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
header->dimensions[2] = 1;
|
header.dimensions[2] = 1;
|
||||||
header->flags |= IMG_FLAG_CUBEMAP;
|
header.flags |= IMG_FLAG_CUBEMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::FillHeader3D(IwiHeader* header, Texture3D* texture)
|
void IwiWriter::FillHeader3D(IwiHeader& header, const Texture3D& texture)
|
||||||
{
|
{
|
||||||
header->dimensions[0] = static_cast<uint16_t>(texture->GetWidth());
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
header->dimensions[1] = static_cast<uint16_t>(texture->GetHeight());
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
header->dimensions[2] = static_cast<uint16_t>(texture->GetDepth());
|
header.dimensions[2] = static_cast<uint16_t>(texture.GetDepth());
|
||||||
header->flags |= IMG_FLAG_VOLMAP;
|
header.flags |= IMG_FLAG_VOLMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::DumpImage(std::ostream& stream, Texture* texture)
|
void IwiWriter::DumpImage(std::ostream& stream, const Texture* texture)
|
||||||
{
|
{
|
||||||
assert(texture != nullptr);
|
assert(texture != nullptr);
|
||||||
|
|
||||||
@ -116,17 +116,17 @@ void IwiWriter::DumpImage(std::ostream& stream, Texture* texture)
|
|||||||
header.fileSizeForPicmip[currentMipLevel] = currentFileSize;
|
header.fileSizeForPicmip[currentMipLevel] = currentFileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto* texture2D = dynamic_cast<Texture2D*>(texture))
|
if (const auto* texture2D = dynamic_cast<const Texture2D*>(texture))
|
||||||
{
|
{
|
||||||
FillHeader2D(&header, texture2D);
|
FillHeader2D(header, *texture2D);
|
||||||
}
|
}
|
||||||
else if (auto* textureCube = dynamic_cast<TextureCube*>(texture))
|
else if (const auto* textureCube = dynamic_cast<const TextureCube*>(texture))
|
||||||
{
|
{
|
||||||
FillHeaderCube(&header, textureCube);
|
FillHeaderCube(header, *textureCube);
|
||||||
}
|
}
|
||||||
else if (auto* texture3D = dynamic_cast<Texture3D*>(texture))
|
else if (const auto* texture3D = dynamic_cast<const Texture3D*>(texture))
|
||||||
{
|
{
|
||||||
FillHeader3D(&header, texture3D);
|
FillHeader3D(header, *texture3D);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -139,6 +139,6 @@ void IwiWriter::DumpImage(std::ostream& stream, Texture* texture)
|
|||||||
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)
|
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)
|
||||||
{
|
{
|
||||||
const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
|
const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
|
||||||
stream.write(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), mipLevelSize);
|
stream.write(reinterpret_cast<const char*>(texture->GetBufferForMipLevel(currentMipLevel)), mipLevelSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@ namespace iwi27
|
|||||||
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
|
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
|
||||||
|
|
||||||
static void WriteVersion(std::ostream& stream);
|
static void WriteVersion(std::ostream& stream);
|
||||||
static void FillHeader2D(IwiHeader* header, Texture2D* texture);
|
static void FillHeader2D(IwiHeader& header, const Texture2D& texture);
|
||||||
static void FillHeaderCube(IwiHeader* header, TextureCube* texture);
|
static void FillHeaderCube(IwiHeader& header, const TextureCube& texture);
|
||||||
static void FillHeader3D(IwiHeader* header, Texture3D* texture);
|
static void FillHeader3D(IwiHeader& header, const Texture3D& texture);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IwiWriter();
|
IwiWriter();
|
||||||
@ -25,6 +25,6 @@ namespace iwi27
|
|||||||
|
|
||||||
bool SupportsImageFormat(const ImageFormat* imageFormat) override;
|
bool SupportsImageFormat(const ImageFormat* imageFormat) override;
|
||||||
std::string GetFileExtension() override;
|
std::string GetFileExtension() override;
|
||||||
void DumpImage(std::ostream& stream, Texture* texture) override;
|
void DumpImage(std::ostream& stream, const Texture* texture) override;
|
||||||
};
|
};
|
||||||
} // namespace iwi27
|
} // namespace iwi27
|
||||||
|
@ -49,27 +49,27 @@ void IwiWriter::WriteVersion(std::ostream& stream)
|
|||||||
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion));
|
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::FillHeader2D(IwiHeader* header, Texture2D* texture)
|
void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture)
|
||||||
{
|
{
|
||||||
header->dimensions[0] = static_cast<uint16_t>(texture->GetWidth());
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
header->dimensions[1] = static_cast<uint16_t>(texture->GetHeight());
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
header->dimensions[2] = 1u;
|
header.dimensions[2] = 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::FillHeaderCube(IwiHeader* header, TextureCube* texture)
|
void IwiWriter::FillHeaderCube(IwiHeader& header, const TextureCube& texture)
|
||||||
{
|
{
|
||||||
header->dimensions[0] = static_cast<uint16_t>(texture->GetWidth());
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
header->dimensions[1] = static_cast<uint16_t>(texture->GetHeight());
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
header->dimensions[2] = 1u;
|
header.dimensions[2] = 1u;
|
||||||
header->flags |= IMG_FLAG_CUBEMAP;
|
header.flags |= IMG_FLAG_CUBEMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::FillHeader3D(IwiHeader* header, Texture3D* texture)
|
void IwiWriter::FillHeader3D(IwiHeader& header, const Texture3D& texture)
|
||||||
{
|
{
|
||||||
header->dimensions[0] = static_cast<uint16_t>(texture->GetWidth());
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
header->dimensions[1] = static_cast<uint16_t>(texture->GetHeight());
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
header->dimensions[2] = static_cast<uint16_t>(texture->GetDepth());
|
header.dimensions[2] = static_cast<uint16_t>(texture.GetDepth());
|
||||||
header->flags |= IMG_FLAG_VOLMAP;
|
header.flags |= IMG_FLAG_VOLMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IwiWriter::SupportsImageFormat(const ImageFormat* imageFormat)
|
bool IwiWriter::SupportsImageFormat(const ImageFormat* imageFormat)
|
||||||
@ -82,7 +82,7 @@ std::string IwiWriter::GetFileExtension()
|
|||||||
return ".iwi";
|
return ".iwi";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::DumpImage(std::ostream& stream, Texture* texture)
|
void IwiWriter::DumpImage(std::ostream& stream, const Texture* texture)
|
||||||
{
|
{
|
||||||
assert(texture != nullptr);
|
assert(texture != nullptr);
|
||||||
|
|
||||||
@ -108,17 +108,17 @@ void IwiWriter::DumpImage(std::ostream& stream, Texture* texture)
|
|||||||
header.fileSizeForPicmip[currentMipLevel] = currentFileSize;
|
header.fileSizeForPicmip[currentMipLevel] = currentFileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto* texture2D = dynamic_cast<Texture2D*>(texture))
|
if (const auto* texture2D = dynamic_cast<const Texture2D*>(texture))
|
||||||
{
|
{
|
||||||
FillHeader2D(&header, texture2D);
|
FillHeader2D(header, *texture2D);
|
||||||
}
|
}
|
||||||
else if (auto* textureCube = dynamic_cast<TextureCube*>(texture))
|
else if (const auto* textureCube = dynamic_cast<const TextureCube*>(texture))
|
||||||
{
|
{
|
||||||
FillHeaderCube(&header, textureCube);
|
FillHeaderCube(header, *textureCube);
|
||||||
}
|
}
|
||||||
else if (auto* texture3D = dynamic_cast<Texture3D*>(texture))
|
else if (const auto* texture3D = dynamic_cast<const Texture3D*>(texture))
|
||||||
{
|
{
|
||||||
FillHeader3D(&header, texture3D);
|
FillHeader3D(header, *texture3D);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -131,6 +131,6 @@ void IwiWriter::DumpImage(std::ostream& stream, Texture* texture)
|
|||||||
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)
|
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)
|
||||||
{
|
{
|
||||||
const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
|
const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
|
||||||
stream.write(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), mipLevelSize);
|
stream.write(reinterpret_cast<const char*>(texture->GetBufferForMipLevel(currentMipLevel)), mipLevelSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@ namespace iwi6
|
|||||||
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
|
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
|
||||||
|
|
||||||
static void WriteVersion(std::ostream& stream);
|
static void WriteVersion(std::ostream& stream);
|
||||||
static void FillHeader2D(IwiHeader* header, Texture2D* texture);
|
static void FillHeader2D(IwiHeader& header, const Texture2D& texture);
|
||||||
static void FillHeaderCube(IwiHeader* header, TextureCube* texture);
|
static void FillHeaderCube(IwiHeader& header, const TextureCube& texture);
|
||||||
static void FillHeader3D(IwiHeader* header, Texture3D* texture);
|
static void FillHeader3D(IwiHeader& header, const Texture3D& texture);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IwiWriter();
|
IwiWriter();
|
||||||
@ -25,6 +25,6 @@ namespace iwi6
|
|||||||
|
|
||||||
bool SupportsImageFormat(const ImageFormat* imageFormat) override;
|
bool SupportsImageFormat(const ImageFormat* imageFormat) override;
|
||||||
std::string GetFileExtension() override;
|
std::string GetFileExtension() override;
|
||||||
void DumpImage(std::ostream& stream, Texture* texture) override;
|
void DumpImage(std::ostream& stream, const Texture* texture) override;
|
||||||
};
|
};
|
||||||
} // namespace iwi6
|
} // namespace iwi6
|
||||||
|
@ -49,27 +49,27 @@ void IwiWriter::WriteVersion(std::ostream& stream)
|
|||||||
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion));
|
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::FillHeader2D(IwiHeader* header, Texture2D* texture)
|
void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture)
|
||||||
{
|
{
|
||||||
header->dimensions[0] = static_cast<uint16_t>(texture->GetWidth());
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
header->dimensions[1] = static_cast<uint16_t>(texture->GetHeight());
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
header->dimensions[2] = 1u;
|
header.dimensions[2] = 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::FillHeaderCube(IwiHeader* header, TextureCube* texture)
|
void IwiWriter::FillHeaderCube(IwiHeader& header, const TextureCube& texture)
|
||||||
{
|
{
|
||||||
header->dimensions[0] = static_cast<uint16_t>(texture->GetWidth());
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
header->dimensions[1] = static_cast<uint16_t>(texture->GetHeight());
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
header->dimensions[2] = 1u;
|
header.dimensions[2] = 1u;
|
||||||
header->flags |= IMG_FLAG_MAPTYPE_CUBE;
|
header.flags |= IMG_FLAG_MAPTYPE_CUBE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::FillHeader3D(IwiHeader* header, Texture3D* texture)
|
void IwiWriter::FillHeader3D(IwiHeader& header, const Texture3D& texture)
|
||||||
{
|
{
|
||||||
header->dimensions[0] = static_cast<uint16_t>(texture->GetWidth());
|
header.dimensions[0] = static_cast<uint16_t>(texture.GetWidth());
|
||||||
header->dimensions[1] = static_cast<uint16_t>(texture->GetHeight());
|
header.dimensions[1] = static_cast<uint16_t>(texture.GetHeight());
|
||||||
header->dimensions[2] = static_cast<uint16_t>(texture->GetDepth());
|
header.dimensions[2] = static_cast<uint16_t>(texture.GetDepth());
|
||||||
header->flags |= IMG_FLAG_MAPTYPE_3D;
|
header.flags |= IMG_FLAG_MAPTYPE_3D;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IwiWriter::SupportsImageFormat(const ImageFormat* imageFormat)
|
bool IwiWriter::SupportsImageFormat(const ImageFormat* imageFormat)
|
||||||
@ -82,7 +82,7 @@ std::string IwiWriter::GetFileExtension()
|
|||||||
return ".iwi";
|
return ".iwi";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwiWriter::DumpImage(std::ostream& stream, Texture* texture)
|
void IwiWriter::DumpImage(std::ostream& stream, const Texture* texture)
|
||||||
{
|
{
|
||||||
assert(texture != nullptr);
|
assert(texture != nullptr);
|
||||||
|
|
||||||
@ -108,17 +108,17 @@ void IwiWriter::DumpImage(std::ostream& stream, Texture* texture)
|
|||||||
header.fileSizeForPicmip[currentMipLevel] = currentFileSize;
|
header.fileSizeForPicmip[currentMipLevel] = currentFileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto* texture2D = dynamic_cast<Texture2D*>(texture))
|
if (const auto* texture2D = dynamic_cast<const Texture2D*>(texture))
|
||||||
{
|
{
|
||||||
FillHeader2D(&header, texture2D);
|
FillHeader2D(header, *texture2D);
|
||||||
}
|
}
|
||||||
else if (auto* textureCube = dynamic_cast<TextureCube*>(texture))
|
else if (const auto* textureCube = dynamic_cast<const TextureCube*>(texture))
|
||||||
{
|
{
|
||||||
FillHeaderCube(&header, textureCube);
|
FillHeaderCube(header, *textureCube);
|
||||||
}
|
}
|
||||||
else if (auto* texture3D = dynamic_cast<Texture3D*>(texture))
|
else if (const auto* texture3D = dynamic_cast<const Texture3D*>(texture))
|
||||||
{
|
{
|
||||||
FillHeader3D(&header, texture3D);
|
FillHeader3D(header, *texture3D);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -131,6 +131,6 @@ void IwiWriter::DumpImage(std::ostream& stream, Texture* texture)
|
|||||||
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)
|
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)
|
||||||
{
|
{
|
||||||
const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
|
const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
|
||||||
stream.write(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), mipLevelSize);
|
stream.write(reinterpret_cast<const char*>(texture->GetBufferForMipLevel(currentMipLevel)), mipLevelSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@ namespace iwi8
|
|||||||
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
|
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
|
||||||
|
|
||||||
static void WriteVersion(std::ostream& stream);
|
static void WriteVersion(std::ostream& stream);
|
||||||
static void FillHeader2D(IwiHeader* header, Texture2D* texture);
|
static void FillHeader2D(IwiHeader& header, const Texture2D& texture);
|
||||||
static void FillHeaderCube(IwiHeader* header, TextureCube* texture);
|
static void FillHeaderCube(IwiHeader& header, const TextureCube& texture);
|
||||||
static void FillHeader3D(IwiHeader* header, Texture3D* texture);
|
static void FillHeader3D(IwiHeader& header, const Texture3D& texture);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IwiWriter();
|
IwiWriter();
|
||||||
@ -25,6 +25,6 @@ namespace iwi8
|
|||||||
|
|
||||||
bool SupportsImageFormat(const ImageFormat* imageFormat) override;
|
bool SupportsImageFormat(const ImageFormat* imageFormat) override;
|
||||||
std::string GetFileExtension() override;
|
std::string GetFileExtension() override;
|
||||||
void DumpImage(std::ostream& stream, Texture* texture) override;
|
void DumpImage(std::ostream& stream, const Texture* texture) override;
|
||||||
};
|
};
|
||||||
} // namespace iwi8
|
} // namespace iwi8
|
||||||
|
@ -13,12 +13,12 @@
|
|||||||
#include "SearchPath/SearchPathFilesystem.h"
|
#include "SearchPath/SearchPathFilesystem.h"
|
||||||
#include "SearchPath/SearchPaths.h"
|
#include "SearchPath/SearchPaths.h"
|
||||||
#include "UnlinkerArgs.h"
|
#include "UnlinkerArgs.h"
|
||||||
#include "Utils/Arguments/ArgumentParser.h"
|
|
||||||
#include "Utils/ClassUtils.h"
|
#include "Utils/ClassUtils.h"
|
||||||
#include "Utils/ObjFileStream.h"
|
#include "Utils/ObjFileStream.h"
|
||||||
#include "ZoneLoading.h"
|
#include "ZoneLoading.h"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <format>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -35,13 +35,32 @@ const IZoneDefWriter* const ZONE_DEF_WRITERS[]{
|
|||||||
|
|
||||||
class Unlinker::Impl
|
class Unlinker::Impl
|
||||||
{
|
{
|
||||||
UnlinkerArgs m_args;
|
public:
|
||||||
SearchPaths m_search_paths;
|
/**
|
||||||
SearchPathFilesystem* m_last_zone_search_path;
|
* \copydoc Unlinker::Start
|
||||||
std::set<std::string> m_absolute_search_paths;
|
*/
|
||||||
|
bool Start(const int argc, const char** argv)
|
||||||
|
{
|
||||||
|
auto shouldContinue = true;
|
||||||
|
if (!m_args.ParseArgs(argc, argv, shouldContinue))
|
||||||
|
return false;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Zone>> m_loaded_zones;
|
if (!shouldContinue)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!BuildSearchPaths())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!LoadZones())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto result = UnlinkZones();
|
||||||
|
|
||||||
|
UnloadZones();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
_NODISCARD bool ShouldLoadObj() const
|
_NODISCARD bool ShouldLoadObj() const
|
||||||
{
|
{
|
||||||
return m_args.m_task != UnlinkerArgs::ProcessingTask::LIST && !m_args.m_skip_obj;
|
return m_args.m_task != UnlinkerArgs::ProcessingTask::LIST && !m_args.m_skip_obj;
|
||||||
@ -51,14 +70,12 @@ class Unlinker::Impl
|
|||||||
* \brief Loads a search path.
|
* \brief Loads a search path.
|
||||||
* \param searchPath The search path to load.
|
* \param searchPath The search path to load.
|
||||||
*/
|
*/
|
||||||
void LoadSearchPath(ISearchPath* searchPath) const
|
void LoadSearchPath(ISearchPath& searchPath) const
|
||||||
{
|
{
|
||||||
if (ShouldLoadObj())
|
if (ShouldLoadObj())
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
{
|
std::cout << std::format("Loading search path: \"{}\"\n", searchPath.GetPath());
|
||||||
printf("Loading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjLoading::LoadIWDsInSearchPath(searchPath);
|
ObjLoading::LoadIWDsInSearchPath(searchPath);
|
||||||
}
|
}
|
||||||
@ -68,14 +85,12 @@ class Unlinker::Impl
|
|||||||
* \brief Unloads a search path.
|
* \brief Unloads a search path.
|
||||||
* \param searchPath The search path to unload.
|
* \param searchPath The search path to unload.
|
||||||
*/
|
*/
|
||||||
void UnloadSearchPath(ISearchPath* searchPath) const
|
void UnloadSearchPath(ISearchPath& searchPath) const
|
||||||
{
|
{
|
||||||
if (ShouldLoadObj())
|
if (ShouldLoadObj())
|
||||||
{
|
{
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
{
|
std::cout << std::format("Unloading search path: \"{}\"\n", searchPath.GetPath());
|
||||||
printf("Unloading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjLoading::UnloadIWDsInSearchPath(searchPath);
|
ObjLoading::UnloadIWDsInSearchPath(searchPath);
|
||||||
}
|
}
|
||||||
@ -93,19 +108,18 @@ class Unlinker::Impl
|
|||||||
|
|
||||||
if (m_last_zone_search_path != nullptr && m_last_zone_search_path->GetPath() == absoluteZoneDirectory)
|
if (m_last_zone_search_path != nullptr && m_last_zone_search_path->GetPath() == absoluteZoneDirectory)
|
||||||
{
|
{
|
||||||
searchPathsForZone.IncludeSearchPath(m_last_zone_search_path);
|
searchPathsForZone.IncludeSearchPath(m_last_zone_search_path.get());
|
||||||
}
|
}
|
||||||
else if (m_absolute_search_paths.find(absoluteZoneDirectory) == m_absolute_search_paths.end())
|
else if (m_absolute_search_paths.find(absoluteZoneDirectory) == m_absolute_search_paths.end())
|
||||||
{
|
{
|
||||||
if (m_last_zone_search_path != nullptr)
|
if (m_last_zone_search_path)
|
||||||
{
|
{
|
||||||
UnloadSearchPath(m_last_zone_search_path);
|
UnloadSearchPath(*m_last_zone_search_path);
|
||||||
delete m_last_zone_search_path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_last_zone_search_path = new SearchPathFilesystem(absoluteZoneDirectory);
|
m_last_zone_search_path = std::make_unique<SearchPathFilesystem>(absoluteZoneDirectory);
|
||||||
searchPathsForZone.IncludeSearchPath(m_last_zone_search_path);
|
searchPathsForZone.IncludeSearchPath(m_last_zone_search_path.get());
|
||||||
LoadSearchPath(m_last_zone_search_path);
|
LoadSearchPath(*m_last_zone_search_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* iwd : IWD::Repository)
|
for (auto* iwd : IWD::Repository)
|
||||||
@ -128,12 +142,12 @@ class Unlinker::Impl
|
|||||||
|
|
||||||
if (!fs::is_directory(absolutePath))
|
if (!fs::is_directory(absolutePath))
|
||||||
{
|
{
|
||||||
printf("Could not find directory of search path: \"%s\"\n", path.c_str());
|
std::cerr << std::format("Could not find directory of search path: \"{}\"\n", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto searchPath = std::make_unique<SearchPathFilesystem>(absolutePath.string());
|
auto searchPath = std::make_unique<SearchPathFilesystem>(absolutePath.string());
|
||||||
LoadSearchPath(searchPath.get());
|
LoadSearchPath(*searchPath);
|
||||||
m_search_paths.CommitSearchPath(std::move(searchPath));
|
m_search_paths.CommitSearchPath(std::move(searchPath));
|
||||||
|
|
||||||
m_absolute_search_paths.insert(absolutePath.string());
|
m_absolute_search_paths.insert(absolutePath.string());
|
||||||
@ -141,16 +155,12 @@ class Unlinker::Impl
|
|||||||
|
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
{
|
{
|
||||||
printf("%u SearchPaths%s\n", m_absolute_search_paths.size(), !m_absolute_search_paths.empty() ? ":" : "");
|
std::cout << std::format("{} SearchPaths{}\n", m_absolute_search_paths.size(), !m_absolute_search_paths.empty() ? ":" : "");
|
||||||
for (const auto& absoluteSearchPath : m_absolute_search_paths)
|
for (const auto& absoluteSearchPath : m_absolute_search_paths)
|
||||||
{
|
std::cout << std::format(" \"{}\"\n", absoluteSearchPath);
|
||||||
printf(" \"%s\"\n", absoluteSearchPath.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_absolute_search_paths.empty())
|
if (!m_absolute_search_paths.empty())
|
||||||
{
|
std::cerr << "\n";
|
||||||
puts("");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -165,7 +175,7 @@ class Unlinker::Impl
|
|||||||
std::ofstream zoneDefinitionFile(zoneDefinitionFilePath, std::fstream::out | std::fstream::binary);
|
std::ofstream zoneDefinitionFile(zoneDefinitionFilePath, std::fstream::out | std::fstream::binary);
|
||||||
if (!zoneDefinitionFile.is_open())
|
if (!zoneDefinitionFile.is_open())
|
||||||
{
|
{
|
||||||
printf("Failed to open file for zone definition file of zone \"%s\".\n", zone->m_name.c_str());
|
std::cerr << std::format("Failed to open file for zone definition file of zone \"{}\".\n", zone->m_name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,9 +191,7 @@ class Unlinker::Impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
std::cerr << std::format("Failed to find writer for zone definition file of zone \"{}\".\n", zone->m_name);
|
||||||
printf("Failed to find writer for zone definition file of zone \"%s\".\n", zone->m_name.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneDefinitionFile.close();
|
zoneDefinitionFile.close();
|
||||||
return result;
|
return result;
|
||||||
@ -202,7 +210,7 @@ class Unlinker::Impl
|
|||||||
stream = std::ofstream(gdtFilePath, std::fstream::out | std::fstream::binary);
|
stream = std::ofstream(gdtFilePath, std::fstream::out | std::fstream::binary);
|
||||||
if (!stream.is_open())
|
if (!stream.is_open())
|
||||||
{
|
{
|
||||||
printf("Failed to open file for zone definition file of zone \"%s\".\n", zone->m_name.c_str());
|
std::cerr << std::format("Failed to open file for zone definition file of zone \"{}\".\n", zone->m_name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +244,7 @@ class Unlinker::Impl
|
|||||||
{
|
{
|
||||||
if (!handledSpecifiedAssets[i])
|
if (!handledSpecifiedAssets[i])
|
||||||
{
|
{
|
||||||
std::cerr << "Unknown asset type \"" << m_args.m_specified_asset_types[i] << "\"\n";
|
std::cerr << std::format("Unknown asset type \"{}\"\n", m_args.m_specified_asset_types[i]);
|
||||||
anySpecifiedValueInvalid = true;
|
anySpecifiedValueInvalid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,10 +270,11 @@ class Unlinker::Impl
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Performs the tasks specified by the command line arguments on the specified zone.
|
* \brief Performs the tasks specified by the command line arguments on the specified zone.
|
||||||
|
* \param searchPath The search path for obj data.
|
||||||
* \param zone The zone to handle.
|
* \param zone The zone to handle.
|
||||||
* \return \c true if handling the zone was successful, otherwise \c false.
|
* \return \c true if handling the zone was successful, otherwise \c false.
|
||||||
*/
|
*/
|
||||||
bool HandleZone(Zone* zone) const
|
bool HandleZone(ISearchPath& searchPath, Zone* zone) const
|
||||||
{
|
{
|
||||||
if (m_args.m_task == UnlinkerArgs::ProcessingTask::LIST)
|
if (m_args.m_task == UnlinkerArgs::ProcessingTask::LIST)
|
||||||
{
|
{
|
||||||
@ -288,6 +297,7 @@ class Unlinker::Impl
|
|||||||
AssetDumpingContext context;
|
AssetDumpingContext context;
|
||||||
context.m_zone = zone;
|
context.m_zone = zone;
|
||||||
context.m_base_path = outputFolderPath;
|
context.m_base_path = outputFolderPath;
|
||||||
|
context.m_obj_search_path = &searchPath;
|
||||||
|
|
||||||
if (m_args.m_use_gdt)
|
if (m_args.m_use_gdt)
|
||||||
{
|
{
|
||||||
@ -318,7 +328,7 @@ class Unlinker::Impl
|
|||||||
{
|
{
|
||||||
if (!fs::is_regular_file(zonePath))
|
if (!fs::is_regular_file(zonePath))
|
||||||
{
|
{
|
||||||
printf("Could not find file \"%s\".\n", zonePath.c_str());
|
std::cerr << std::format("Could not find file \"{}\".\n", zonePath);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,20 +340,15 @@ class Unlinker::Impl
|
|||||||
auto zone = ZoneLoading::LoadZone(zonePath);
|
auto zone = ZoneLoading::LoadZone(zonePath);
|
||||||
if (zone == nullptr)
|
if (zone == nullptr)
|
||||||
{
|
{
|
||||||
printf("Failed to load zone \"%s\".\n", zonePath.c_str());
|
std::cerr << std::format("Failed to load zone \"{}\".\n", zonePath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
{
|
std::cout << std::format("Loaded zone \"{}\"\n", zone->m_name);
|
||||||
printf("Loaded zone \"%s\"\n", zone->m_name.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShouldLoadObj())
|
if (ShouldLoadObj())
|
||||||
{
|
ObjLoading::LoadReferencedContainersForZone(searchPathsForZone, *zone);
|
||||||
ObjLoading::LoadReferencedContainersForZone(&searchPathsForZone, zone.get());
|
|
||||||
ObjLoading::LoadObjDataForZone(&searchPathsForZone, zone.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_loaded_zones.emplace_back(std::move(zone));
|
m_loaded_zones.emplace_back(std::move(zone));
|
||||||
}
|
}
|
||||||
@ -356,17 +361,17 @@ class Unlinker::Impl
|
|||||||
for (auto i = m_loaded_zones.rbegin(); i != m_loaded_zones.rend(); ++i)
|
for (auto i = m_loaded_zones.rbegin(); i != m_loaded_zones.rend(); ++i)
|
||||||
{
|
{
|
||||||
auto& loadedZone = *i;
|
auto& loadedZone = *i;
|
||||||
std::string zoneName = loadedZone->m_name;
|
|
||||||
|
// Copy zone name since we deallocate before logging
|
||||||
|
const auto zoneName = loadedZone->m_name;
|
||||||
|
|
||||||
if (ShouldLoadObj())
|
if (ShouldLoadObj())
|
||||||
{
|
ObjLoading::UnloadContainersOfZone(*loadedZone);
|
||||||
ObjLoading::UnloadContainersOfZone(loadedZone.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
loadedZone.reset();
|
loadedZone.reset();
|
||||||
|
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Unloaded zone \"" << zoneName << "\"\n";
|
std::cout << std::format("Unloaded zone \"{}\"\n", zoneName);
|
||||||
}
|
}
|
||||||
m_loaded_zones.clear();
|
m_loaded_zones.clear();
|
||||||
}
|
}
|
||||||
@ -377,7 +382,7 @@ class Unlinker::Impl
|
|||||||
{
|
{
|
||||||
if (!fs::is_regular_file(zonePath))
|
if (!fs::is_regular_file(zonePath))
|
||||||
{
|
{
|
||||||
printf("Could not find file \"%s\".\n", zonePath.c_str());
|
std::cerr << std::format("Could not find file \"{}\".\n", zonePath);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,63 +398,37 @@ class Unlinker::Impl
|
|||||||
auto zone = ZoneLoading::LoadZone(zonePath);
|
auto zone = ZoneLoading::LoadZone(zonePath);
|
||||||
if (zone == nullptr)
|
if (zone == nullptr)
|
||||||
{
|
{
|
||||||
printf("Failed to load zone \"%s\".\n", zonePath.c_str());
|
std::cerr << std::format("Failed to load zone \"{}\".\n", zonePath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
zoneName = zone->m_name;
|
zoneName = zone->m_name;
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Loaded zone \"" << zoneName << "\"\n";
|
std::cout << std::format("Loaded zone \"{}\"\n", zoneName);
|
||||||
|
|
||||||
if (ShouldLoadObj())
|
if (ShouldLoadObj())
|
||||||
{
|
ObjLoading::LoadReferencedContainersForZone(searchPathsForZone, *zone);
|
||||||
ObjLoading::LoadReferencedContainersForZone(&searchPathsForZone, zone.get());
|
|
||||||
ObjLoading::LoadObjDataForZone(&searchPathsForZone, zone.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!HandleZone(zone.get()))
|
if (!HandleZone(searchPathsForZone, zone.get()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ShouldLoadObj())
|
if (ShouldLoadObj())
|
||||||
ObjLoading::UnloadContainersOfZone(zone.get());
|
ObjLoading::UnloadContainersOfZone(*zone);
|
||||||
|
|
||||||
zone.reset();
|
zone.reset();
|
||||||
if (m_args.m_verbose)
|
if (m_args.m_verbose)
|
||||||
std::cout << "Unloaded zone \"" << zoneName << "\"\n";
|
std::cout << std::format("Unloaded zone \"{}\"\n", zoneName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
UnlinkerArgs m_args;
|
||||||
Impl()
|
SearchPaths m_search_paths;
|
||||||
{
|
std::unique_ptr<SearchPathFilesystem> m_last_zone_search_path;
|
||||||
m_last_zone_search_path = nullptr;
|
std::set<std::string> m_absolute_search_paths;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
std::vector<std::unique_ptr<Zone>> m_loaded_zones;
|
||||||
* \copydoc Unlinker::Start
|
|
||||||
*/
|
|
||||||
bool Start(const int argc, const char** argv)
|
|
||||||
{
|
|
||||||
auto shouldContinue = true;
|
|
||||||
if (!m_args.ParseArgs(argc, argv, shouldContinue))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!shouldContinue)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!BuildSearchPaths())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!LoadZones())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto result = UnlinkZones();
|
|
||||||
|
|
||||||
UnloadZones();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Unlinker::Unlinker()
|
Unlinker::Unlinker()
|
||||||
|
@ -44,9 +44,6 @@ typedef void ID3D11VertexShader;
|
|||||||
typedef void ID3D11InputLayout;
|
typedef void ID3D11InputLayout;
|
||||||
typedef void ID3D11Buffer;
|
typedef void ID3D11Buffer;
|
||||||
|
|
||||||
// OAT Types
|
|
||||||
typedef void Texture;
|
|
||||||
|
|
||||||
// Unimportant cpp keywords
|
// Unimportant cpp keywords
|
||||||
#define __unaligned
|
#define __unaligned
|
||||||
#define volatile
|
#define volatile
|
||||||
|
@ -14,7 +14,6 @@ reorder:
|
|||||||
use GfxTexture;
|
use GfxTexture;
|
||||||
set reusable loadDef;
|
set reusable loadDef;
|
||||||
set block loadDef XFILE_BLOCK_TEMP;
|
set block loadDef XFILE_BLOCK_TEMP;
|
||||||
set condition texture never;
|
|
||||||
|
|
||||||
// GfxImageLoadDef
|
// GfxImageLoadDef
|
||||||
use GfxImageLoadDef;
|
use GfxImageLoadDef;
|
||||||
|
@ -14,7 +14,6 @@ reorder:
|
|||||||
use GfxTexture;
|
use GfxTexture;
|
||||||
set reusable loadDef;
|
set reusable loadDef;
|
||||||
set block loadDef XFILE_BLOCK_TEMP;
|
set block loadDef XFILE_BLOCK_TEMP;
|
||||||
set condition texture never;
|
|
||||||
|
|
||||||
// GfxImageLoadDef
|
// GfxImageLoadDef
|
||||||
use GfxImageLoadDef;
|
use GfxImageLoadDef;
|
||||||
|
@ -14,7 +14,6 @@ reorder:
|
|||||||
use GfxTexture;
|
use GfxTexture;
|
||||||
set reusable loadDef;
|
set reusable loadDef;
|
||||||
set block loadDef XFILE_BLOCK_TEMP;
|
set block loadDef XFILE_BLOCK_TEMP;
|
||||||
set condition texture never;
|
|
||||||
|
|
||||||
// GfxImageLoadDef
|
// GfxImageLoadDef
|
||||||
use GfxImageLoadDef;
|
use GfxImageLoadDef;
|
||||||
|
@ -15,7 +15,6 @@ reorder:
|
|||||||
use GfxTexture;
|
use GfxTexture;
|
||||||
set reusable loadDef;
|
set reusable loadDef;
|
||||||
set block loadDef XFILE_BLOCK_TEMP;
|
set block loadDef XFILE_BLOCK_TEMP;
|
||||||
set condition texture never;
|
|
||||||
|
|
||||||
// GfxImageLoadDef
|
// GfxImageLoadDef
|
||||||
use GfxImageLoadDef;
|
use GfxImageLoadDef;
|
||||||
|
@ -16,7 +16,6 @@ use GfxTexture;
|
|||||||
set reusable loadDef;
|
set reusable loadDef;
|
||||||
set block loadDef XFILE_BLOCK_TEMP;
|
set block loadDef XFILE_BLOCK_TEMP;
|
||||||
set condition basemap never;
|
set condition basemap never;
|
||||||
set condition texture never;
|
|
||||||
|
|
||||||
// GfxImageLoadDef
|
// GfxImageLoadDef
|
||||||
use GfxImageLoadDef;
|
use GfxImageLoadDef;
|
||||||
|
@ -21,7 +21,7 @@ namespace
|
|||||||
"lorem,ipsum");
|
"lorem,ipsum");
|
||||||
|
|
||||||
Zone zone("MockZone", 0, &g_GameIW3);
|
Zone zone("MockZone", 0, &g_GameIW3);
|
||||||
MockAssetLoadingManager assetLoadingManager(&zone, &searchPath);
|
MockAssetLoadingManager assetLoadingManager(zone, searchPath);
|
||||||
|
|
||||||
AssetLoaderStringTable assetLoader;
|
AssetLoaderStringTable assetLoader;
|
||||||
MemoryManager memory;
|
MemoryManager memory;
|
||||||
|
@ -22,7 +22,7 @@ namespace
|
|||||||
"lorem,ipsum");
|
"lorem,ipsum");
|
||||||
|
|
||||||
Zone zone("MockZone", 0, &g_GameIW4);
|
Zone zone("MockZone", 0, &g_GameIW4);
|
||||||
MockAssetLoadingManager assetLoadingManager(&zone, &searchPath);
|
MockAssetLoadingManager assetLoadingManager(zone, searchPath);
|
||||||
|
|
||||||
AssetLoaderStringTable assetLoader;
|
AssetLoaderStringTable assetLoader;
|
||||||
MemoryManager memory;
|
MemoryManager memory;
|
||||||
|
@ -29,7 +29,7 @@ namespace test::game::iw4::menu::parsing::it
|
|||||||
public:
|
public:
|
||||||
MenuParsingItHelper()
|
MenuParsingItHelper()
|
||||||
: m_zone("MockZone", 0, &g_GameIW4),
|
: m_zone("MockZone", 0, &g_GameIW4),
|
||||||
m_manager(&m_zone, &m_search_path)
|
m_manager(m_zone, m_search_path)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ namespace
|
|||||||
"lorem,ipsum");
|
"lorem,ipsum");
|
||||||
|
|
||||||
Zone zone("MockZone", 0, &g_GameIW5);
|
Zone zone("MockZone", 0, &g_GameIW5);
|
||||||
MockAssetLoadingManager assetLoadingManager(&zone, &searchPath);
|
MockAssetLoadingManager assetLoadingManager(zone, searchPath);
|
||||||
|
|
||||||
AssetLoaderStringTable assetLoader;
|
AssetLoaderStringTable assetLoader;
|
||||||
MemoryManager memory;
|
MemoryManager memory;
|
||||||
|
@ -21,7 +21,7 @@ namespace
|
|||||||
"lorem,ipsum");
|
"lorem,ipsum");
|
||||||
|
|
||||||
Zone zone("MockZone", 0, &g_GameT5);
|
Zone zone("MockZone", 0, &g_GameT5);
|
||||||
MockAssetLoadingManager assetLoadingManager(&zone, &searchPath);
|
MockAssetLoadingManager assetLoadingManager(zone, searchPath);
|
||||||
|
|
||||||
AssetLoaderStringTable assetLoader;
|
AssetLoaderStringTable assetLoader;
|
||||||
MemoryManager memory;
|
MemoryManager memory;
|
||||||
|
@ -21,7 +21,7 @@ namespace
|
|||||||
"lorem,ipsum");
|
"lorem,ipsum");
|
||||||
|
|
||||||
Zone zone("MockZone", 0, &g_GameT6);
|
Zone zone("MockZone", 0, &g_GameT6);
|
||||||
MockAssetLoadingManager assetLoadingManager(&zone, &searchPath);
|
MockAssetLoadingManager assetLoadingManager(zone, searchPath);
|
||||||
|
|
||||||
AssetLoaderStringTable assetLoader;
|
AssetLoaderStringTable assetLoader;
|
||||||
MemoryManager memory;
|
MemoryManager memory;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "MockAssetLoadingManager.h"
|
#include "MockAssetLoadingManager.h"
|
||||||
|
|
||||||
MockAssetLoadingManager::MockAssetLoadingManager(Zone* zone, ISearchPath* searchPath)
|
MockAssetLoadingManager::MockAssetLoadingManager(Zone& zone, ISearchPath& searchPath)
|
||||||
: m_zone(zone),
|
: m_zone(zone),
|
||||||
m_mock_gdt(std::make_unique<Gdt>()),
|
m_mock_gdt(std::make_unique<Gdt>()),
|
||||||
m_context(std::make_unique<AssetLoadingContext>(zone, searchPath, std::vector({m_mock_gdt.get()})))
|
m_context(std::make_unique<AssetLoadingContext>(zone, searchPath, std::vector({m_mock_gdt.get()})))
|
||||||
|
@ -7,14 +7,14 @@
|
|||||||
|
|
||||||
class MockAssetLoadingManager final : public IAssetLoadingManager
|
class MockAssetLoadingManager final : public IAssetLoadingManager
|
||||||
{
|
{
|
||||||
Zone* m_zone;
|
Zone& m_zone;
|
||||||
std::unique_ptr<Gdt> m_mock_gdt;
|
std::unique_ptr<Gdt> m_mock_gdt;
|
||||||
std::unique_ptr<AssetLoadingContext> m_context;
|
std::unique_ptr<AssetLoadingContext> m_context;
|
||||||
std::map<std::string, std::unique_ptr<XAssetInfoGeneric>> m_added_assets;
|
std::map<std::string, std::unique_ptr<XAssetInfoGeneric>> m_added_assets;
|
||||||
std::multimap<std::string, std::unique_ptr<XAssetInfoGeneric>> m_available_dependencies;
|
std::multimap<std::string, std::unique_ptr<XAssetInfoGeneric>> m_available_dependencies;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MockAssetLoadingManager(Zone* zone, ISearchPath* searchPath);
|
MockAssetLoadingManager(Zone& zone, ISearchPath& searchPath);
|
||||||
|
|
||||||
_NODISCARD AssetLoadingContext* GetAssetLoadingContext() const override;
|
_NODISCARD AssetLoadingContext* GetAssetLoadingContext() const override;
|
||||||
XAssetInfoGeneric* AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo) override;
|
XAssetInfoGeneric* AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo) override;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user