diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index fd1b6aaf9d..2c9d0c13a2 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -11,6 +11,7 @@ A new header is inserted each time a *tag* is created. - WebGL: added missing IBL builder to TypeScript annotations - engine: Fix incorrect precision restoration when computing accurate world translations - engine: make `MaterialInstance` public API friendly to `std::string_view` parameters +- gltfio: add 'detach' methods to allow ownership transfer of entities and components ## v1.25.4 diff --git a/libs/gltfio/include/gltfio/FilamentAsset.h b/libs/gltfio/include/gltfio/FilamentAsset.h index 8165bbb6a1..31318d8dd6 100644 --- a/libs/gltfio/include/gltfio/FilamentAsset.h +++ b/libs/gltfio/include/gltfio/FilamentAsset.h @@ -334,6 +334,23 @@ public: void addEntitiesToScene(filament::Scene& targetScene, const Entity* entities, size_t count, SceneMask sceneFilter); + /** + * Releases ownership of entities and their Filament components. + * + * This makes the client take responsibility for destroying Filament + * components (e.g. Renderable, TransformManager component) as well as + * the underlying entities. + */ + void detachFilamentComponents(); + + /** + * Releases ownership of material instances. + * + * This makes the client take responsibility for destroying MaterialInstance + * objects. The getMaterialInstances query becomes invalid after detachment. + */ + void detachMaterialInstances(); + /*! \cond PRIVATE */ FilamentInstance** getAssetInstances() noexcept; diff --git a/libs/gltfio/src/FFilamentAsset.h b/libs/gltfio/src/FFilamentAsset.h index 2f091b3da4..7d82e59427 100644 --- a/libs/gltfio/src/FFilamentAsset.h +++ b/libs/gltfio/src/FFilamentAsset.h @@ -255,9 +255,17 @@ struct FFilamentAsset : public FilamentAsset { void addEntitiesToScene(filament::Scene& targetScene, const Entity* entities, size_t count, SceneMask sceneFilter); + void detachFilamentComponents() { + mDetachedFilamentComponents = true; + } + + void detachMaterialInstances() { + mMaterialInstances.clear(); + } + // end public API - void takeOwnership(filament::Texture* texture) { + void attachTexture(filament::Texture* texture) { mTextures.push_back(texture); } @@ -299,6 +307,7 @@ struct FFilamentAsset : public FilamentAsset { DependencyGraph mDependencyGraph; tsl::htrie_map> mNameToEntity; utils::CString mAssetExtras; + bool mDetachedFilamentComponents = false; // Sentinels for situations where ResourceLoader needs to generate data. const cgltf_accessor mGenerateNormals = {}; diff --git a/libs/gltfio/src/FilamentAsset.cpp b/libs/gltfio/src/FilamentAsset.cpp index 99dfcce181..bf95fcb1e7 100644 --- a/libs/gltfio/src/FilamentAsset.cpp +++ b/libs/gltfio/src/FilamentAsset.cpp @@ -33,10 +33,11 @@ using namespace utils; namespace filament::gltfio { FFilamentAsset::~FFilamentAsset() { + // Free transient load-time data if they haven't been freed yet. releaseSourceData(); - // The only things we need to free in the instances are their animators. - // The union of all instance entities will be destroyed below. + // Destroy all instance objects and their animators. Instance entities / components are + // destroyed later in this method because they are owned by the asset. for (FFilamentInstance* instance : mInstances) { delete instance->animator; delete instance; @@ -45,21 +46,30 @@ FFilamentAsset::~FFilamentAsset() { delete mAnimator; delete mWireframe; - mEngine->destroy(mRoot); - mEntityManager->destroy(mRoot); - - for (auto entity : mEntities) { - // Destroy the entity's renderable, light, transform, and camera components. - mEngine->destroy(entity); - // Destroy the name component. - if (mNameManager) { + // Destroy name components. + if (mNameManager) { + for (auto entity : mEntities) { mNameManager->removeComponent(entity); } - // Destroy the node component. - mNodeManager->destroy(entity); - // Destroy the actual entity. - mEntityManager->destroy(entity); } + + // Destroy gltfio node components. + for (auto entity : mEntities) { + mNodeManager->destroy(entity); + + } + + // Destroy all renderable, light, transform, and camera components, + // then destroy the actual entities. This includes instances. + if (!mDetachedFilamentComponents) { + mEngine->destroy(mRoot); + mEntityManager->destroy(mRoot); + for (auto entity : mEntities) { + mEngine->destroy(entity); + mEntityManager->destroy(entity); + } + } + for (auto mi : mMaterialInstances) { mEngine->destroy(mi); } @@ -283,6 +293,14 @@ void FFilamentAsset::addEntitiesToScene(Scene& targetScene, const Entity* entiti } } +void FilamentAsset::detachFilamentComponents() { + upcast(this)->detachFilamentComponents(); +} + +void FilamentAsset::detachMaterialInstances() { + upcast(this)->detachMaterialInstances(); +} + size_t FilamentAsset::getEntityCount() const noexcept { return upcast(this)->getEntityCount(); } diff --git a/libs/gltfio/src/ResourceLoader.cpp b/libs/gltfio/src/ResourceLoader.cpp index ff01074551..02203c8c24 100644 --- a/libs/gltfio/src/ResourceLoader.cpp +++ b/libs/gltfio/src/ResourceLoader.cpp @@ -687,7 +687,7 @@ Texture* ResourceLoader::Impl::getOrCreateTexture(FFilamentAsset* asset, const T << provider->getPushMessage() << io::endl; asset->mDependencyGraph.markAsError(tb.materialInstance); } else { - asset->takeOwnership(texture); + asset->attachTexture(texture); } return texture;