diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp index 14eded2..6a63b83 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp @@ -40,14 +40,82 @@ class Asset: public AssetBase public: using FLAT_ASSET = typename ASSET::FLAT; + /** + * Constructor + * + * Will default initialize header + * + */ Asset() { m_header.type_id = GetTypeID(); m_header.type_name = eastl::string {GetTypeName()}; } - explicit Asset(const eastl::span p_flatbuffer): - Asset() + Asset(const Asset& p_asset) = default; + Asset(Asset&& p_asset) = default; + + ~Asset() = default; + + /** + * Get the header of the asset + * + * \return The header of the asset + */ + [[nodiscard]] + const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const + { + return m_header; + } + + /** + * Set the name of the asset + * + * \param p_name The name of the asset + */ + void SetName(const eastl::string_view p_name) + { + m_header.name = p_name; + } + + /** + * Set the version of the asset + * + * \param p_name The version of the asset + */ + void SetVersion(const std::uint32_t p_version) + { + m_header.version = p_version; + } + + /** + * Get the asset + * + * \return The asset + */ + [[nodiscard]] + const typename FLAT_ASSET::NativeTableType& GetAsset() const + { + return m_asset; + } + + /** + * Get the asset + * + * \return The asset + */ + [[nodiscard]] + typename FLAT_ASSET::NativeTableType& GetAsset() + { + return m_asset; + } + + /** + * Unpack a flatbuffer to the asset + * + * \param p_flatbuffer The flatbuffer to unpack + */ + void Unpack(const eastl::span p_flatbuffer) { #ifdef BIGFOOT_NOT_OPTIMIZED flatbuffers::Verifier verifier {std::bit_cast(p_flatbuffer.data()), p_flatbuffer.size()}; @@ -67,41 +135,14 @@ class Asset: public AssetBase flatbuffers::GetRoot(asset->inner_asset()->data())->UnPackTo(&m_asset, nullptr); } - Asset(const Asset& p_asset) = default; - Asset(Asset&& p_asset) = default; - - ~Asset() = default; - +#ifdef BIGFOOT_TOOLMODE + /** + * Pack the asset to a flatbuffer + * + * \return The packed asset + */ [[nodiscard]] - const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const - { - return m_header; - } - - void SetName(const eastl::string_view p_name) - { - m_header.name = p_name; - } - - void SetVersion(const std::uint32_t p_version) - { - m_header.version = p_version; - } - - [[nodiscard]] - const typename FLAT_ASSET::NativeTableType& GetAsset() const - { - return m_asset; - } - - [[nodiscard]] - typename FLAT_ASSET::NativeTableType& GetAsset() - { - return m_asset; - } - - [[nodiscard]] - eastl::vector Save() const + eastl::vector Pack() const { flatbuffers::FlatBufferBuilder innerAssetFbb; innerAssetFbb.Finish(FLAT_ASSET::Pack(innerAssetFbb, &m_asset)); @@ -117,15 +158,26 @@ class Asset: public AssetBase return eastl::vector {std::bit_cast(assetFbb.GetBufferPointer()), std::bit_cast(assetFbb.GetBufferPointer() + assetFbb.GetSize())}; } +#endif + /** + * Get the AssetTypeID + * + * \return The AssetTypeIPD + */ [[nodiscard]] - static std::uint64_t GetTypeID() + static AssetTypeID GetTypeID() { - static const std::uint64_t typeID = rapidhash(FLAT_ASSET::GetFullyQualifiedName(), - std::strlen(FLAT_ASSET::GetFullyQualifiedName())); + static const AssetTypeID typeID = rapidhash(FLAT_ASSET::GetFullyQualifiedName(), + std::strlen(FLAT_ASSET::GetFullyQualifiedName())); return typeID; } + /** + * Get the type name + * + * \return The type name + */ [[nodiscard]] static eastl::string_view GetTypeName() { @@ -136,7 +188,13 @@ class Asset: public AssetBase Asset& operator=(Asset&& p_asset) = default; private: + /** + * The asset + */ typename FLAT_ASSET::NativeTableType m_asset; + /** + * The asset header + */ ::Flat::Bigfoot::AssetHeaderT m_header; }; } // namespace Bigfoot diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetConcepts.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetConcepts.hpp index 1038b9a..57a42ee 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetConcepts.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetConcepts.hpp @@ -32,9 +32,9 @@ concept AssetTraits = requires { */ template concept AssetType = std::derived_from && !std::same_as && - requires(const ASSET& p_asset) { - { ASSET::GetTypeID() } -> std::convertible_to; - { p_asset.GetHeader().uuid } -> std::convertible_to; - }; + requires(const ASSET& p_asset) { + { ASSET::GetTypeID() } -> std::convertible_to; + { p_asset.GetHeader().uuid } -> std::convertible_to; + }; } // namespace Bigfoot #endif diff --git a/Bigfoot/Sources/System/Include/System/UUID/UUID.hpp b/Bigfoot/Sources/System/Include/System/UUID/UUID.hpp index 9014a2a..5f5bec1 100644 --- a/Bigfoot/Sources/System/Include/System/UUID/UUID.hpp +++ b/Bigfoot/Sources/System/Include/System/UUID/UUID.hpp @@ -15,6 +15,11 @@ class UUID public: static constexpr std::uint32_t UUID_BYTE_SIZE = 16; + /** + * Constructor + * Will default initialize an UUID to a valid value + * + */ UUID(); /** diff --git a/Bigfoot/Tests/Engine/Asset/Asset.cpp b/Bigfoot/Tests/Engine/Asset/Asset.cpp index e69de29..f1f7103 100644 --- a/Bigfoot/Tests/Engine/Asset/Asset.cpp +++ b/Bigfoot/Tests/Engine/Asset/Asset.cpp @@ -0,0 +1,152 @@ +/********************************************************************* + * \file Asset.cpp + * + * \author Romain BOULLARD + * \date August 2026 + *********************************************************************/ +#include + +#include +#include +#include + +#include + +namespace Bigfoot +{ +class AssetFixture: public ::testing::Test +{ + protected: + /** + * Packs a header and an asset the same way Asset::Pack() does. Pack() is intentionally + * BIGFOOT_TOOLMODE-only: game code must never be able to build asset buffers. + */ + template + static eastl::vector PackAssetBuffer(const ::Flat::Bigfoot::AssetHeaderT& p_header, + const typename ASSET::FLAT_ASSET::NativeTableType& p_asset) + { + flatbuffers::FlatBufferBuilder innerAssetFbb; + innerAssetFbb.Finish(ASSET::FLAT_ASSET::Pack(innerAssetFbb, &p_asset)); + + ::Flat::Bigfoot::AssetT asset; + asset.header = eastl::make_unique<::Flat::Bigfoot::AssetHeaderT>(p_header); + asset.inner_asset = eastl::vector {innerAssetFbb.GetBufferPointer(), + innerAssetFbb.GetBufferPointer() + innerAssetFbb.GetSize()}; + + flatbuffers::FlatBufferBuilder assetFbb; + assetFbb.Finish(::Flat::Bigfoot::Asset::Pack(assetFbb, &asset)); + + return eastl::vector {std::bit_cast(assetFbb.GetBufferPointer()), + std::bit_cast(assetFbb.GetBufferPointer() + assetFbb.GetSize())}; + } + + AssetA m_asset; +}; + +/****************************************************************************************/ + +TEST_F(AssetFixture, Constructor_ShouldInitializeHeaderTypeIdAndTypeName) +{ + EXPECT_EQ(m_asset.GetHeader().type_id, AssetA::GetTypeID()); + EXPECT_EQ(m_asset.GetHeader().type_name, eastl::string {AssetA::GetTypeName()}); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, SetName_ShouldSetTheName) +{ + m_asset.SetName("MyAsset"); + + EXPECT_STREQ(m_asset.GetHeader().name.c_str(), "MyAsset"); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, SetVersion_ShouldSetTheVersion) +{ + m_asset.SetVersion(5); + + EXPECT_EQ(m_asset.GetHeader().version, 5); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, GetAsset_ShouldReturnAMutableReferenceToTheUnderlyingAsset) +{ + m_asset.GetAsset().health = 10; + + EXPECT_EQ(m_asset.GetAsset().health, 10); + EXPECT_EQ(std::as_const(m_asset).GetAsset().health, 10); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, GetTypeID_ShouldBeStableAcrossCalls) +{ + EXPECT_EQ(AssetA::GetTypeID(), AssetA::GetTypeID()); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, GetTypeID_ShouldBeDifferentForDifferentAssetTypes) +{ + EXPECT_NE(AssetA::GetTypeID(), AssetB::GetTypeID()); + EXPECT_NE(AssetA::GetTypeID(), AssetC::GetTypeID()); + EXPECT_NE(AssetB::GetTypeID(), AssetC::GetTypeID()); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, GetTypeName_ShouldReturnTheFlatbufferFullyQualifiedName) +{ + EXPECT_EQ(AssetA::GetTypeName(), eastl::string_view {AssetA::FLAT_ASSET::GetFullyQualifiedName()}); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, Unpack_ShouldPopulateTheHeaderAndTheAsset) +{ + ::Flat::Bigfoot::AssetHeaderT header; + header.name = "MyAsset"; + header.version = 3; + header.type_id = AssetA::GetTypeID(); + header.type_name = eastl::string {AssetA::GetTypeName()}; + + AssetA::FLAT_ASSET::NativeTableType inner; + inner.health = 42; + inner.mana = 7; + + m_asset.Unpack(PackAssetBuffer(header, inner)); + + EXPECT_EQ(m_asset.GetHeader().uuid, header.uuid); + EXPECT_STREQ(m_asset.GetHeader().name.c_str(), header.name.c_str()); + EXPECT_EQ(m_asset.GetHeader().version, header.version); + EXPECT_EQ(m_asset.GetHeader().type_id, header.type_id); + EXPECT_STREQ(m_asset.GetHeader().type_name.c_str(), header.type_name.c_str()); + EXPECT_EQ(m_asset.GetAsset().health, 42); + EXPECT_EQ(m_asset.GetAsset().mana, 7); +} + +/****************************************************************************************/ + +#ifdef BIGFOOT_TOOLMODE +TEST_F(AssetFixture, PackThenUnpack_ShouldRoundTripTheHeaderAndTheAsset) +{ + m_asset.SetName("MyAsset"); + m_asset.SetVersion(3); + m_asset.GetAsset().health = 42; + m_asset.GetAsset().mana = 7; + + AssetA unpacked; + unpacked.Unpack(m_asset.Pack()); + + EXPECT_EQ(unpacked.GetHeader().uuid, m_asset.GetHeader().uuid); + EXPECT_STREQ(unpacked.GetHeader().name.c_str(), m_asset.GetHeader().name.c_str()); + EXPECT_EQ(unpacked.GetHeader().version, m_asset.GetHeader().version); + EXPECT_EQ(unpacked.GetHeader().type_id, m_asset.GetHeader().type_id); + EXPECT_STREQ(unpacked.GetHeader().type_name.c_str(), m_asset.GetHeader().type_name.c_str()); + EXPECT_EQ(unpacked.GetAsset().health, m_asset.GetAsset().health); + EXPECT_EQ(unpacked.GetAsset().mana, m_asset.GetAsset().mana); +} +#endif +} // namespace Bigfoot diff --git a/Bigfoot/Tests/Engine/Asset/Reference.cpp b/Bigfoot/Tests/Engine/Asset/Reference.cpp index 0342556..22805c4 100644 --- a/Bigfoot/Tests/Engine/Asset/Reference.cpp +++ b/Bigfoot/Tests/Engine/Asset/Reference.cpp @@ -39,7 +39,7 @@ TEST_F(HardReferenceFixture, GetUUID_ShouldReturnTheUUID) { UUID uuid; HardReference hardRef {uuid}; - + EXPECT_EQ(hardRef.GetUUID(), uuid); } diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.hpp index 245c486..485804f 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.hpp @@ -22,11 +22,6 @@ class AssetA: public Asset public: AssetA() = default; - AssetA(const eastl::span p_flatbuffer): - Asset(p_flatbuffer) - { - } - AssetA(const AssetA& p_asset) = default; AssetA(AssetA&& p_asset) = default; diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.hpp index cc87034..9323034 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.hpp @@ -22,11 +22,6 @@ class AssetB: public Asset public: AssetB() = default; - AssetB(const eastl::span p_flatbuffer): - Asset(p_flatbuffer) - { - } - AssetB(const AssetB& p_asset) = delete; AssetB(AssetB&& p_asset) = default; diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.hpp index ecf5fae..c719e50 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.hpp @@ -25,11 +25,6 @@ class AssetC: public Asset GetAsset().inner_table = eastl::make_unique<::Flat::Bigfoot::InnerTableT>(); } - AssetC(const eastl::span p_flatbuffer): - Asset(p_flatbuffer) - { - } - AssetC(const AssetC& p_asset) = delete; AssetC(AssetC&& p_asset) = default;