diff --git a/Bigfoot/Benchmarks/Engine/Asset/Reference.cpp b/Bigfoot/Benchmarks/Engine/Asset/Reference.cpp index f0ac226..6086e51 100644 --- a/Bigfoot/Benchmarks/Engine/Asset/Reference.cpp +++ b/Bigfoot/Benchmarks/Engine/Asset/Reference.cpp @@ -30,7 +30,7 @@ class ReferenceFixture: public benchmark::Fixture SetActiveAssetLibrary(&m_library); std::ignore = m_library.Insert(&m_container); - m_uuid = m_container.Insert()->GetAsset()->GetHeader().uuid; + m_uuid = CreateAsset()->GetHeader().uuid; m_reference.emplace(m_uuid); } diff --git a/Bigfoot/Benchmarks/Engine/SerializationManager/SerializationManager.cpp b/Bigfoot/Benchmarks/Engine/SerializationManager/SerializationManager.cpp index 445bc72..fe52aef 100644 --- a/Bigfoot/Benchmarks/Engine/SerializationManager/SerializationManager.cpp +++ b/Bigfoot/Benchmarks/Engine/SerializationManager/SerializationManager.cpp @@ -317,7 +317,7 @@ BENCHMARK_DEFINE_F(SerializationManagerFixture, SaveAsset)(benchmark::State& sta for (auto _: state) { state.PauseTiming(); - auto* asset = static_cast(container.Insert()->GetAsset()); + auto* asset = CreateAsset(); asset->SetName(asset->GetHeader().uuid.ToString().c_str()); asset->GetAsset().payload.assign(ASSET_PAYLOAD_SIZE, std::uint8_t {0xAB}); for (std::uint32_t j = 0; j < REFS_PER_ROOT; ++j) @@ -359,7 +359,7 @@ BENCHMARK_DEFINE_F(SerializationManagerFixture, SaveAssets)(benchmark::State& st std::size_t batchBytes = 0; for (std::size_t i = 0; i < batchSize; ++i) { - auto* asset = static_cast(container.Insert()->GetAsset()); + auto* asset = CreateAsset(); asset->SetName(asset->GetHeader().uuid.ToString().c_str()); asset->GetAsset().payload.assign(ASSET_PAYLOAD_SIZE, std::uint8_t {0xAB}); for (std::uint32_t j = 0; j < REFS_PER_ROOT; ++j) diff --git a/Bigfoot/Sources/Engine/Asset/Asset.cpp b/Bigfoot/Sources/Engine/Asset/AssetBase.cpp similarity index 97% rename from Bigfoot/Sources/Engine/Asset/Asset.cpp rename to Bigfoot/Sources/Engine/Asset/AssetBase.cpp index 950a1bc..dcdd941 100644 --- a/Bigfoot/Sources/Engine/Asset/Asset.cpp +++ b/Bigfoot/Sources/Engine/Asset/AssetBase.cpp @@ -1,10 +1,10 @@ /********************************************************************* - * \file Asset.cpp + * \file AssetBase.cpp * * \author Romain BOULLARD * \date April 2026 *********************************************************************/ -#include +#include #include diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp index 6b54468..8cb03ab 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp @@ -6,7 +6,10 @@ *********************************************************************/ #ifndef BIGFOOT_ENGINE_ASSET_ASSET_HPP #define BIGFOOT_ENGINE_ASSET_ASSET_HPP +#include #include +#include +#include #include #include @@ -18,95 +21,6 @@ namespace Bigfoot { -class AssetBase -{ - public: - virtual ~AssetBase() = default; - - /** - * Get the header of the asset - * - * \return The header of the asset - */ - [[nodiscard]] - virtual const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const = 0; - - /** - * Get the HardReferences the flatbuffer has - * - * \param p_flatbuffer The flatbuffer - * \return The UUIDs of the HardReferences - */ - [[nodiscard]] - virtual eastl::vector GetHardReferences(const eastl::span p_flatbuffer) const = 0; - - /** - * Unpack a flatbuffer to the asset - * - * \param p_flatbuffer The flatbuffer to unpack - */ - virtual void Unpack(const eastl::span p_flatbuffer) = 0; - - /** - * Pack the asset to a flatbuffer - * - * \return The packed asset - */ - [[nodiscard]] - virtual eastl::vector Pack() const = 0; - - protected: - AssetBase() = default; - - AssetBase(const AssetBase& p_asset) = delete; - AssetBase(AssetBase&& p_asset) = default; - - AssetBase& operator=(const AssetBase& p_asset) = delete; - AssetBase& operator=(AssetBase&& p_asset) = default; - - class HardReferenceVisitor: public flatbuffers::IterationVisitor - { - public: - void Field(size_t p_fieldIndex, - size_t p_setIndex, - const flatbuffers::ElementaryType p_type, - const bool p_isVector, - const flatbuffers::TypeTable* p_typeTable, - const char* p_name, - const std::uint8_t* p_val) override; - - void Element(size_t p_index, - const flatbuffers::ElementaryType p_type, - const flatbuffers::TypeTable* p_typeTable, - const std::uint8_t* p_val) override; - - /** - * Get the visited HardReference - * - * \return The visited HardReferences - */ - [[nodiscard]] - eastl::vector GetUUIDs() const; - - private: - /** - * Visit an element in the flatbuffer - * - * \param p_type The element type - * \param p_typeTable The element typetable - * \param p_val The element - */ - void Visit(const flatbuffers::ElementaryType p_type, - const flatbuffers::TypeTable* p_typeTable, - const std::uint8_t* p_val); - - /** - * The HardReferences visited so far - */ - ankerl::unordered_dense::set m_uuids; - }; -}; - template requires AssetTraits class Asset: public AssetBase @@ -277,6 +191,24 @@ class Asset: public AssetBase */ ::Flat::Bigfoot::AssetHeaderT m_header; }; + +/** + * Create an asset and insert it into its corresponding AssetContainer + * + * \tparam ASSET The Asset type + * \return The created asset, nullptr if no AssetContainer is registered for ASSET + */ +template + requires AssetType +[[nodiscard]] +ASSET* CreateAsset() +{ + AssetContainerBase* container = g_activeAssetLibrary->GetAssetContainer(ASSET::GetTypeID()); + CRITICAL_ASSERT(EngineAssertHandler, container != nullptr, "No AssetContainer registered for this asset type!"); + + ContainerHandle* handle = container->Insert(); + return static_cast(handle->GetAsset()); +} } // namespace Bigfoot #endif diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetBase.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetBase.hpp new file mode 100644 index 0000000..682d58f --- /dev/null +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetBase.hpp @@ -0,0 +1,110 @@ +/********************************************************************* + * \file AssetBase.hpp + * + * \author Romain BOULLARD + * \date April 2026 + *********************************************************************/ +#ifndef BIGFOOT_ENGINE_ASSET_ASSETBASE_HPP +#define BIGFOOT_ENGINE_ASSET_ASSETBASE_HPP +#include + +#include + +#include +#include +#include +#include + +namespace Bigfoot +{ +class AssetBase +{ + public: + virtual ~AssetBase() = default; + + /** + * Get the header of the asset + * + * \return The header of the asset + */ + [[nodiscard]] + virtual const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const = 0; + + /** + * Get the HardReferences the flatbuffer has + * + * \param p_flatbuffer The flatbuffer + * \return The UUIDs of the HardReferences + */ + [[nodiscard]] + virtual eastl::vector GetHardReferences(const eastl::span p_flatbuffer) const = 0; + + /** + * Unpack a flatbuffer to the asset + * + * \param p_flatbuffer The flatbuffer to unpack + */ + virtual void Unpack(const eastl::span p_flatbuffer) = 0; + + /** + * Pack the asset to a flatbuffer + * + * \return The packed asset + */ + [[nodiscard]] + virtual eastl::vector Pack() const = 0; + + protected: + AssetBase() = default; + + AssetBase(const AssetBase& p_asset) = delete; + AssetBase(AssetBase&& p_asset) = default; + + AssetBase& operator=(const AssetBase& p_asset) = delete; + AssetBase& operator=(AssetBase&& p_asset) = default; + + class HardReferenceVisitor: public flatbuffers::IterationVisitor + { + public: + void Field(size_t p_fieldIndex, + size_t p_setIndex, + const flatbuffers::ElementaryType p_type, + const bool p_isVector, + const flatbuffers::TypeTable* p_typeTable, + const char* p_name, + const std::uint8_t* p_val) override; + + void Element(size_t p_index, + const flatbuffers::ElementaryType p_type, + const flatbuffers::TypeTable* p_typeTable, + const std::uint8_t* p_val) override; + + /** + * Get the visited HardReference + * + * \return The visited HardReferences + */ + [[nodiscard]] + eastl::vector GetUUIDs() const; + + private: + /** + * Visit an element in the flatbuffer + * + * \param p_type The element type + * \param p_typeTable The element typetable + * \param p_val The element + */ + void Visit(const flatbuffers::ElementaryType p_type, + const flatbuffers::TypeTable* p_typeTable, + const std::uint8_t* p_val); + + /** + * The HardReferences visited so far + */ + ankerl::unordered_dense::set m_uuids; + }; +}; +} // namespace Bigfoot + +#endif diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp index a0abeaf..e607e1c 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp @@ -6,7 +6,7 @@ *********************************************************************/ #ifndef BIGFOOT_ENGINE_ASSET_ASSETCONTAINER_HPP #define BIGFOOT_ENGINE_ASSET_ASSETCONTAINER_HPP -#include +#include #include #include diff --git a/Bigfoot/Tests/Engine/Asset/Asset.cpp b/Bigfoot/Tests/Engine/Asset/Asset.cpp index ae6ef60..d1d6c82 100644 --- a/Bigfoot/Tests/Engine/Asset/Asset.cpp +++ b/Bigfoot/Tests/Engine/Asset/Asset.cpp @@ -20,6 +20,10 @@ class AssetFixture: public ::testing::Test protected: void SetUp() override { + SetActiveAssetLibrary(&m_library); + std::ignore = m_library.Insert(&m_containerA); + std::ignore = m_library.Insert(&m_containerB); + const UUID uuidA = m_assetA.GetHeader().uuid; const UUID uuidB = m_assetB.GetHeader().uuid; @@ -35,6 +39,15 @@ class AssetFixture: public ::testing::Test m_assetC.GetAsset().asset_b_refs.push_back(SoftReference {uuidB}); } + void TearDown() override + { + SetActiveAssetLibrary(&g_assetLibrary); + } + + AssetLibrary m_library; + AssetContainer m_containerA; + AssetContainer m_containerB; + AssetA m_assetA; AssetB m_assetB; AssetC m_assetC; @@ -117,4 +130,45 @@ TEST_F(AssetFixture, GetHardReferences_ShouldReturnTheHardReferencesOfTheAsset) EXPECT_THAT(hardReferences, ::testing::UnorderedElementsAre(m_assetA.GetHeader().uuid, m_assetB.GetHeader().uuid)); } + +/****************************************************************************************/ + +TEST_F(AssetFixture, CreateAsset_ShouldReturnTheCreatedAsset) +{ + EXPECT_NE(CreateAsset(), nullptr); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, CreateAsset_ShouldCreateUniqueAssets) +{ + const AssetA* first = CreateAsset(); + const AssetA* second = CreateAsset(); + + EXPECT_NE(first->GetHeader().uuid, second->GetHeader().uuid); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, CreateAsset_ShouldReturnTheSameAssetAsItsContainerHandle) +{ + const AssetA* asset = CreateAsset(); + const ContainerHandle* handle = m_containerA.AcquireContainerHandle(asset->GetHeader().uuid); + + EXPECT_EQ(handle->GetAsset(), asset); +} + +/****************************************************************************************/ + +TEST_F(AssetFixture, CreateAsset_ShouldInsertTheAssetIntoItsCorrespondingContainer) +{ + const AssetA* assetA = CreateAsset(); + const AssetB* assetB = CreateAsset(); + + EXPECT_TRUE(m_containerA.Has(assetA->GetHeader().uuid)); + EXPECT_FALSE(m_containerB.Has(assetA->GetHeader().uuid)); + + EXPECT_TRUE(m_containerB.Has(assetB->GetHeader().uuid)); + EXPECT_FALSE(m_containerA.Has(assetB->GetHeader().uuid)); +} } // namespace Bigfoot diff --git a/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp b/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp index 42b9255..53ba2a4 100644 --- a/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp +++ b/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp @@ -184,11 +184,11 @@ TEST_F(AssetLibraryFixture, ProcessPendingRemovals_ShouldCascadeThroughHardRefer { // leaf - AssetA* leaf = static_cast(m_containerA.Insert()->GetAsset()); + AssetA* leaf = CreateAsset(); leafUUID = leaf->GetHeader().uuid; // middle --> leaf - AssetB* middle = static_cast(m_containerB.Insert()->GetAsset()); + AssetB* middle = CreateAsset(); middle->GetAsset().ref_a = HardReference {leafUUID}; middleUUID = middle->GetHeader().uuid; @@ -196,7 +196,7 @@ TEST_F(AssetLibraryFixture, ProcessPendingRemovals_ShouldCascadeThroughHardRefer // / \ // v v // middle --> leaf - AssetC* root = static_cast(m_containerC.Insert()->GetAsset()); + AssetC* root = CreateAsset(); root->GetAsset().asset_b_ref = HardReference {middleUUID}; root->GetAsset().inner_table->asset_a_ref = HardReference {leafUUID}; rootUUID = root->GetHeader().uuid; diff --git a/Bigfoot/Tests/Engine/Asset/Reference.cpp b/Bigfoot/Tests/Engine/Asset/Reference.cpp index b3de0b5..31bb444 100644 --- a/Bigfoot/Tests/Engine/Asset/Reference.cpp +++ b/Bigfoot/Tests/Engine/Asset/Reference.cpp @@ -96,7 +96,7 @@ TYPED_TEST(ReferenceFixture, GetUUID_ShouldReturnTheUUID) TYPED_TEST(ReferenceFixture, Get_ShouldReturnTheAsset) { - const AssetA* inserted = static_cast(this->m_containerA.Insert()->GetAsset()); + const AssetA* inserted = CreateAsset(); const UUID uuid = inserted->GetHeader().uuid; TypeParam ref {uuid}; @@ -120,7 +120,7 @@ TYPED_TEST(ReferenceFixture, Get_ShouldReturnNullptrIfTheAssetDoesNotExist) TYPED_TEST(ReferenceFixture, Get_ShouldReturnNullptrAfterTheAssetIsRemovedFromTheContainer) { - const AssetA* inserted = static_cast(this->m_containerA.Insert()->GetAsset()); + const AssetA* inserted = CreateAsset(); const UUID uuid = inserted->GetHeader().uuid; TypeParam ref {uuid}; @@ -157,7 +157,7 @@ TYPED_TEST(ReferenceFixture, ShouldTouchTheRefCountOfTheHandle) TYPED_TEST(ReferenceFixture, CopyConstructor_ShouldIncrementTheRefCountAndCopyTheState) { - const AssetA* inserted = static_cast(this->m_containerA.Insert()->GetAsset()); + const AssetA* inserted = CreateAsset(); const UUID uuid = inserted->GetHeader().uuid; const ContainerHandle* handle = this->m_containerA.AcquireContainerHandle(uuid); @@ -175,7 +175,7 @@ TYPED_TEST(ReferenceFixture, CopyConstructor_ShouldIncrementTheRefCountAndCopyTh TYPED_TEST(ReferenceFixture, MoveConstructor_ShouldTransferTheStateWithoutChangingTheRefCount) { - const AssetA* inserted = static_cast(this->m_containerA.Insert()->GetAsset()); + const AssetA* inserted = CreateAsset(); const UUID uuid = inserted->GetHeader().uuid; const ContainerHandle* handle = this->m_containerA.AcquireContainerHandle(uuid); diff --git a/Bigfoot/Tests/Engine/SerializationManager/SerializationManager.cpp b/Bigfoot/Tests/Engine/SerializationManager/SerializationManager.cpp index 63f257b..2af0736 100644 --- a/Bigfoot/Tests/Engine/SerializationManager/SerializationManager.cpp +++ b/Bigfoot/Tests/Engine/SerializationManager/SerializationManager.cpp @@ -263,7 +263,7 @@ TEST_F(SerializationManagerFixture, LoadAsset_ShouldSkipAssetsThatAreCaughtInACy TEST_F(SerializationManagerFixture, LoadAsset_ShouldNotReloadAnAssetThatIsAlreadyLoaded) { - AssetA* alreadyLoaded = static_cast(m_containerA.Insert()->GetAsset()); + AssetA* alreadyLoaded = CreateAsset(); alreadyLoaded->SetName("in-memory"); const UUID uuid = alreadyLoaded->GetHeader().uuid; @@ -305,7 +305,7 @@ TEST_F(SerializationManagerFixture, LoadAssets_ShouldLoadEveryRootAndMergeShared #ifdef BIGFOOT_TOOLMODE TEST_F(SerializationManagerFixture, SaveAsset_ShouldSaveTheAsset) { - AssetB* asset = static_cast(m_containerB.Insert()->GetAsset()); + AssetB* asset = CreateAsset(); const UUID referencedUUID; asset->GetAsset().ref_a = HardReference {referencedUUID}; @@ -323,7 +323,7 @@ TEST_F(SerializationManagerFixture, SaveAsset_ShouldSaveTheAsset) TEST_F(SerializationManagerFixture, SaveAsset_ShouldFailAndNotSaveIfAnAssetHardReferencesItself) { - AssetB* asset = static_cast(m_containerB.Insert()->GetAsset()); + AssetB* asset = CreateAsset(); const UUID uuid = asset->GetHeader().uuid; asset->GetAsset().ref_a = HardReference {uuid}; @@ -338,8 +338,8 @@ TEST_F(SerializationManagerFixture, SaveAsset_ShouldFailAndNotSaveIfAnAssetHardR TEST_F(SerializationManagerFixture, SaveAssets_ShouldFailAndNotSaveIfTwoAssetsInTheSameSaveHardReferenceEachOther) { - AssetB* assetX = static_cast(m_containerB.Insert()->GetAsset()); - AssetB* assetY = static_cast(m_containerB.Insert()->GetAsset()); + AssetB* assetX = CreateAsset(); + AssetB* assetY = CreateAsset(); const UUID uuidX = assetX->GetHeader().uuid; const UUID uuidY = assetY->GetHeader().uuid; @@ -361,7 +361,7 @@ TEST_F(SerializationManagerFixture, SaveAssets_ShouldFailAndNotSaveIfTwoAssetsIn TEST_F(SerializationManagerFixture, SaveAssets_ShouldFailAndNotSaveIfAnAlreadySavedHardReferencePointsBackToIt) { - AssetB* asset = static_cast(m_containerB.Insert()->GetAsset()); + AssetB* asset = CreateAsset(); const UUID uuid = asset->GetHeader().uuid; const UUID referencedUUID; asset->GetAsset().ref_a = HardReference {referencedUUID}; @@ -383,8 +383,8 @@ TEST_F(SerializationManagerFixture, SaveAssets_ShouldFailAndNotSaveIfAnAlreadySa TEST_F(SerializationManagerFixture, SaveAssets_ShouldSaveEveryAsset) { - const AssetA* assetX = static_cast(m_containerA.Insert()->GetAsset()); - const AssetA* assetY = static_cast(m_containerA.Insert()->GetAsset()); + const AssetA* assetX = CreateAsset(); + const AssetA* assetY = CreateAsset(); const UUID uuidX = assetX->GetHeader().uuid; const UUID uuidY = assetY->GetHeader().uuid;