diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp index ff05b603c0..08e1ddbb08 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp @@ -94,8 +94,9 @@ namespace CommandSystem return false; } - actor->LoadRemainingAssets(); - actor->CheckFinalizeActor(); + // Because the actor is directly loaded from disk (without going through an actor asset), we need to ask for a blocking + // load for the asset that actor is depend on. + actor->Finalize(EMotionFX::Actor::LoadRequirement::RequireBlockingLoad); // set the actor id in case we have specified it as parameter if (actorID != MCORE_INVALIDINDEX32) diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp index c7c6b86aea..d5f53e72c5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp @@ -52,7 +52,7 @@ namespace EMotionFX AZ::SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(1); + serializeContext->Class()->Version(2); } } @@ -117,21 +117,6 @@ namespace EMotionFX ExporterLib::SaveActor(filename, m_actor.get(), MCore::Endian::ENDIAN_LITTLE, GetMeshAssetId(context)); -#ifdef EMOTIONFX_ACTOR_DEBUG - // Use there line to create a log file and inspect detail debug info - AZStd::string folderPath; - AzFramework::StringFunc::Path::GetFolderPath(filename.c_str(), folderPath); - AZStd::string logFilename = folderPath; - logFilename += "EMotionFXExporter_Log.txt"; - MCore::GetLogManager().CreateLogFile(logFilename.c_str()); - EMotionFX::GetImporter().SetLogDetails(true); - filename += ".xac"; - - // use this line to load the actor from the saved actor file - EMotionFX::Actor* testLoadingActor = EMotionFX::GetImporter().LoadActor(AZStd::string(filename.c_str())); - MCore::Destroy(testLoadingActor); -#endif // EMOTIONFX_ACTOR_DEBUG - static AZ::Data::AssetType emotionFXActorAssetType("{F67CC648-EA51-464C-9F5D-4A9CE41A7F86}"); // from ActorAsset.h in EMotionFX Gem AZ::SceneAPI::Events::ExportProduct& product = context.m_products.AddProduct(AZStd::move(filename), context.m_group.GetId(), emotionFXActorAssetType, AZStd::nullopt, AZStd::nullopt); @@ -141,6 +126,26 @@ namespace EMotionFX product.m_legacyPathDependencies.emplace_back(AZStd::move(materialPathReference)); } + // Mesh asset, skin meta asset and morph target meta asset are sub assets for actor asset. + // In here we set them as the dependency of the actor asset. That make sure those assets get automatically loaded before actor asset. + // Default to the first product until we are able to establish a link between mesh and actor (ATOM-13590). + const AZ::Data::AssetType assetDependencyList[] = { + azrtti_typeid(), + azrtti_typeid(), + azrtti_typeid() + }; + + for (const AZ::Data::AssetType& assetDependency : assetDependencyList) + { + AZStd::optional result = GetFirstProductByType(context, assetDependency); + if (result != AZStd::nullopt) + { + AZ::SceneAPI::Events::ExportProduct exportProduct = result.value(); + exportProduct.m_dependencyFlags = AZ::Data::ProductDependencyInfo::CreateFlags(AZ::Data::AssetLoadBehavior::PreLoad); + product.m_productDependencies.emplace_back(exportProduct); + } + } + return SceneEvents::ProcessingResult::Success; } @@ -171,5 +176,20 @@ namespace EMotionFX return AZStd::nullopt; } + + AZStd::optional ActorGroupExporter::GetFirstProductByType( + const ActorGroupExportContext& context, AZ::Data::AssetType type) + { + const AZStd::vector& products = context.m_products.GetProducts(); + for (const AZ::SceneAPI::Events::ExportProduct& product : products) + { + if (product.m_assetType == type) + { + return product; + } + } + + return AZStd::nullopt; + } } // namespace Pipeline } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.h b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.h index 451d1f4bb4..585126c07b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.h +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.h @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -44,6 +45,8 @@ namespace EMotionFX //! Get the mesh asset id to which the actor is linked to by default. AZStd::optional GetMeshAssetId(const ActorGroupExportContext& context) const; + static AZStd::optional GetFirstProductByType( + const ActorGroupExportContext& context, AZ::Data::AssetType type); AutoRegisteredActor m_actor; AZStd::vector m_actorMaterialReferences; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 403e7ec05a..67f0773aec 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -125,7 +125,6 @@ namespace EMotionFX Actor::~Actor() { - AZ::Data::AssetBus::MultiHandler::BusDisconnect(); ActorNotificationBus::Broadcast(&ActorNotificationBus::Events::OnActorDestroyed, this); GetEventManager().OnDeleteActor(this); @@ -1463,108 +1462,78 @@ namespace EMotionFX return morphTargetMetaAssetInfo.m_assetId.IsValid(); } - void Actor::OnAssetReady(AZ::Data::Asset asset) - { - if (asset == m_meshAsset) - { - m_meshAsset = asset; - } - if (asset == m_skinMetaAsset) - { - m_skinMetaAsset = asset; - } - if (asset == m_morphTargetMetaAsset) - { - m_morphTargetMetaAsset = asset; - } - - CheckFinalizeActor(); - } - - void Actor::CheckFinalizeActor() + void Actor::Finalize(LoadRequirement loadReq) { AZStd::scoped_lock lock(m_mutex); - if (m_meshAsset.IsReady()) + // Load the mesh asset, skin meta asset and morph target asset. + // Those sub assets should have already been setup as dependency of actor asset, so they should already be loaded when we reach here. + // Only exception is that when the actor is not loaded by an actor asset, for which we need to do a blocking load. + if (m_meshAssetId.IsValid()) { - const AZ::Data::AssetId meshAssetId = m_meshAsset.GetId(); - const bool skinMetaAssetExists = DoesSkinMetaAssetExist(meshAssetId); - const bool morphTargetMetaAssetExists = DoesMorphTargetMetaAssetExist(m_meshAsset.GetId()); + // Get the mesh asset. + m_meshAsset = AZ::Data::AssetManager::Instance().GetAsset(m_meshAssetId, AZ::Data::AssetLoadBehavior::PreLoad); + + // Get the skin meta asset. + const AZ::Data::AssetId skinMetaAssetId = ConstructSkinMetaAssetId(m_meshAssetId); + if (DoesSkinMetaAssetExist(m_meshAssetId) && skinMetaAssetId.IsValid()) + { + m_skinMetaAsset = AZ::Data::AssetManager::Instance().GetAsset( + skinMetaAssetId, AZ::Data::AssetLoadBehavior::PreLoad); + } - m_skinToSkeletonIndexMap.clear(); + // Get the morph target meta asset. + const AZ::Data::AssetId morphTargetMetaAssetId = ConstructMorphTargetMetaAssetId(m_meshAssetId); + if (DoesMorphTargetMetaAssetExist(m_meshAssetId) && morphTargetMetaAssetId.IsValid()) + { + m_morphTargetMetaAsset = AZ::Data::AssetManager::Instance().GetAsset( + morphTargetMetaAssetId, AZ::Data::AssetLoadBehavior::PreLoad); + } - // Skin and morph target meta assets are ready, fill the runtime mesh data. - if ((!skinMetaAssetExists || m_skinMetaAsset.IsReady()) && - (!morphTargetMetaAssetExists || m_morphTargetMetaAsset.IsReady())) + if (loadReq == LoadRequirement::RequireBlockingLoad) { - // Optional, not all actors have a skinned meshes. - if (skinMetaAssetExists) + if (m_skinMetaAsset.IsLoading()) { - m_skinToSkeletonIndexMap = ConstructSkinToSkeletonIndexMap(m_skinMetaAsset); + m_skinMetaAsset.BlockUntilLoadComplete(); } - - ConstructMeshes(m_skinToSkeletonIndexMap); - - // Optional, not all actors have morph targets. - if (morphTargetMetaAssetExists) + if (m_morphTargetMetaAsset.IsLoading()) { - ConstructMorphTargets(); + m_morphTargetMetaAsset.BlockUntilLoadComplete(); } - else + if (m_meshAsset.IsLoading()) { - // Optional, not all actors have morph targets. - const size_t numLODLevels = m_meshAsset->GetLodAssets().size(); - mMorphSetups.Resize(numLODLevels); - for (AZ::u32 i = 0; i < numLODLevels; ++i) - { - mMorphSetups[i] = nullptr; - } + m_meshAsset.BlockUntilLoadComplete(); } - - SetActorReady(); - - // Do not release the mesh assets. We need the mesh data to initialize future instances of the render actor instances. - //m_meshAsset.Release(); - //m_skinMetaAsset.Release(); - //m_morphTargetMetaAsset.Release(); } } - } - void Actor::LoadRemainingAssets() - { - // Everything is ready already or no (skeleton-only) or an invalid mesh asset assigned. Emit ready signal directly. - if (m_isReady || !m_meshAssetId.IsValid()) + if (m_meshAsset.IsReady()) { - SetActorReady(); - return; - } - - LoadMeshAssetsQueued(); - } + if (m_skinMetaAsset.IsReady()) + { + m_skinToSkeletonIndexMap = ConstructSkinToSkeletonIndexMap(m_skinMetaAsset); + } + ConstructMeshes(); - void Actor::OnAssetReloaded(AZ::Data::Asset asset) - { - if (asset == m_meshAsset) - { - m_meshAsset = asset; - } - if (asset == m_skinMetaAsset) - { - m_skinMetaAsset = asset; - } - if (asset == m_morphTargetMetaAsset) - { - m_morphTargetMetaAsset = asset; + if (m_morphTargetMetaAsset.IsReady()) + { + ConstructMorphTargets(); + } + else + { + // Optional, not all actors have morph targets. + const size_t numLODLevels = m_meshAsset->GetLodAssets().size(); + mMorphSetups.Resize(numLODLevels); + for (AZ::u32 i = 0; i < numLODLevels; ++i) + { + mMorphSetups[i] = nullptr; + } + } } - CheckFinalizeActor(); - } - - void Actor::SetActorReady() - { m_isReady = true; ActorNotificationBus::Broadcast(&ActorNotificationBus::Events::OnActorReady, this); + // Do not release the mesh assets. We need the mesh data to initialize future instances of the render actor instances. } // update the static AABB (very heavy as it has to create an actor instance, update mesh deformers, calculate the mesh based bounds etc) @@ -2792,37 +2761,6 @@ namespace EMotionFX m_meshAssetId = assetId; } - void Actor::LoadMeshAssetsQueued() - { - AZStd::scoped_lock lock(m_mutex); - - // Mesh asset will be queue loaded on post init. - if (m_meshAssetId.IsValid()) - { - m_isReady = false; - AZ::Data::AssetBus::MultiHandler::BusDisconnect(); - - AZ::Data::AssetBus::MultiHandler::BusConnect(m_meshAssetId); - m_meshAsset = AZ::Data::AssetManager::Instance().GetAsset(m_meshAssetId, AZ::Data::AssetLoadBehavior::Default); - - // Skin meta asset - if (DoesSkinMetaAssetExist(m_meshAssetId)) - { - const AZ::Data::AssetId skinMetaAssetId = ConstructSkinMetaAssetId(m_meshAssetId); - AZ::Data::AssetBus::MultiHandler::BusConnect(skinMetaAssetId); - m_skinMetaAsset = AZ::Data::AssetManager::Instance().GetAsset(skinMetaAssetId, AZ::Data::AssetLoadBehavior::Default); - } - - // Morph target meta asset - if (DoesMorphTargetMetaAssetExist(m_meshAssetId)) - { - const AZ::Data::AssetId morphTargetMetaAssetId = ConstructMorphTargetMetaAssetId(m_meshAssetId); - AZ::Data::AssetBus::MultiHandler::BusConnect(morphTargetMetaAssetId); - m_morphTargetMetaAsset = AZ::Data::AssetManager::Instance().GetAsset(morphTargetMetaAssetId, AZ::Data::AssetLoadBehavior::Default); - } - } - } - Node* Actor::FindMeshJoint(const AZ::Data::Asset& lodModelAsset) const { const AZStd::array_view& sourceMeshes = lodModelAsset->GetMeshes(); @@ -2843,7 +2781,7 @@ namespace EMotionFX return mSkeleton->GetNode(0); } - void Actor::ConstructMeshes(const AZStd::unordered_map& skinToSkeletonIndexMap) + void Actor::ConstructMeshes() { AZ_Assert(m_meshAsset.IsReady(), "Mesh asset should be fully loaded and ready."); @@ -2855,7 +2793,8 @@ namespace EMotionFX SetNumLODLevels(numLODLevels, /*adjustMorphSetup=*/false); const uint32 numNodes = mSkeleton->GetNumNodes(); - // Remove all the materials and add them back based on the meshAsset. Eventually we will remove all the material from Actor and GLActor. + // Remove all the materials and add them back based on the meshAsset. Eventually we will remove all the material from Actor and + // GLActor. RemoveAllMaterials(); mMaterials.Resize(numLODLevels); @@ -2866,7 +2805,7 @@ namespace EMotionFX lodLevels[lodLevel].mNodeInfos.Resize(numNodes); // Create a single mesh for the actor. - Mesh* mesh = Mesh::CreateFromModelLod(lodAsset, skinToSkeletonIndexMap); + Mesh* mesh = Mesh::CreateFromModelLod(lodAsset, m_skinToSkeletonIndexMap); // Find an owning joint for the mesh. Node* meshJoint = FindMeshJoint(lodAsset); @@ -2896,13 +2835,14 @@ namespace EMotionFX continue; } - EMotionFX::SkinningInfoVertexAttributeLayer* skinLayer = static_cast(vertexAttributeLayer); + EMotionFX::SkinningInfoVertexAttributeLayer* skinLayer = + static_cast(vertexAttributeLayer); const AZ::u32 numOrgVerts = skinLayer->GetNumAttributes(); AZStd::set localJointIndices = skinLayer->CalcLocalJointIndices(numOrgVerts); const AZ::u32 numLocalJoints = static_cast(localJointIndices.size()); - // The information about if we want to use dual quat skinning is baked into the mesh chunk and we don't have access to that anymore. - // Default to dual quat skinning. + // The information about if we want to use dual quat skinning is baked into the mesh chunk and we don't have access to that + // anymore. Default to dual quat skinning. const bool dualQuatSkinning = true; if (dualQuatSkinning) { @@ -2970,7 +2910,8 @@ namespace EMotionFX void Actor::ConstructMorphTargets() { - AZ_Assert(m_meshAsset.IsReady() && m_morphTargetMetaAsset.IsReady(), "Mesh as well as morph target meta asset asset should be fully loaded and ready."); + AZ_Assert(m_meshAsset.IsReady() && m_morphTargetMetaAsset.IsReady(), + "Mesh as well as morph target meta asset asset should be fully loaded and ready."); AZStd::vector& lodLevels = m_meshLodData.m_lodLevels; const AZStd::array_view>& lodAssets = m_meshAsset->GetLodAssets(); const size_t numLODLevels = lodAssets.size(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h index 9bf0daf046..3fe9711f18 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h @@ -63,7 +63,6 @@ namespace EMotionFX * still share the same data from the Actor class. The Actor contains information about the hierarchy/structure of the characters. */ class EMFX_API Actor - : private AZ::Data::AssetBus::MultiHandler { public: AZ_CLASS_ALLOCATOR_DECL @@ -101,6 +100,12 @@ namespace EMotionFX uint8 mFlags; // bitfield with MIRRORFLAG_ prefix }; + enum class LoadRequirement : bool + { + RequireBlockingLoad, + AllowAsyncLoad + }; + //------------------------------------------------ /** @@ -885,36 +890,35 @@ namespace EMotionFX bool GetOptimizeSkeleton() const { return m_optimizeSkeleton; } void SetMeshAssetId(const AZ::Data::AssetId& assetId); - void CheckFinalizeActor(); - void LoadMeshAssetsQueued(); - void LoadRemainingAssets(); + AZ::Data::AssetId GetMeshAssetId() const { return m_meshAssetId; }; const AZ::Data::Asset& GetMeshAsset() const { return m_meshAsset; } const AZ::Data::Asset& GetSkinMetaAsset() const { return m_skinMetaAsset; } const AZ::Data::Asset& GetMorphTargetMetaAsset() const { return m_morphTargetMetaAsset; } - const AZStd::unordered_map& GetSkinToSkeletonIndexMap() const { return m_skinToSkeletonIndexMap; } - void SetMeshAsset(AZ::Data::Asset asset) { m_meshAsset = asset; } - void SetSkinMetaAsset(AZ::Data::Asset asset) { m_skinMetaAsset = asset; } - void SetMorphTargetMetaAsset(AZ::Data::Asset asset) { m_morphTargetMetaAsset = asset; } - /** - * Is the actor fully ready? - * @result True in case the actor as well as its dependent files (e.g. mesh, skin, morph targets) are fully loaded and initialized. - **/ + * Is the actor fully ready? + * @result True in case the actor as well as its dependent files (e.g. mesh, skin, morph targets) are fully loaded and initialized. + **/ bool IsReady() const { return m_isReady; } + /** + * Finalize the actor with preload assets (mesh, skinmeta and morph target assets). + * LoadRequirement - We won't need a blocking load if the actor is part of the actor asset, as that will trigger the preload assets + * to load and get ready before finalize has been reached. + * However, if we are calling this on an actor that bypassed the asset system (e.g loading the actor directly from disk), it will require + * a blocking load. This option is now being used because emfx editor does not fully integrate with the asset system. + */ + void Finalize(LoadRequirement loadReq = LoadRequirement::AllowAsyncLoad); + private: void InsertJointAndParents(AZ::u32 jointIndex, AZStd::unordered_set& includedJointIndices); - // AZ::Data::AssetBus::Handler - void OnAssetReady(AZ::Data::Asset asset) override; - void OnAssetReloaded(AZ::Data::Asset asset) override; - AZStd::unordered_map ConstructSkinToSkeletonIndexMap(const AZ::Data::Asset& skinMetaAsset); - void ConstructMeshes(const AZStd::unordered_map& skinToSkeletonIndexMap); + void ConstructMeshes(); void ConstructMorphTargets(); + Node* FindJointByMeshName(const AZStd::string_view meshName) const; // per node info (shared between lods) @@ -966,9 +970,6 @@ namespace EMotionFX Node* FindMeshJoint(const AZ::Data::Asset& lodModelAsset) const; - void SetActorReady(); - bool m_isReady = false; - Skeleton* mSkeleton; /**< The skeleton, containing the nodes and bind pose. */ MCore::Array mDependencies; /**< The dependencies on other actors (shared meshes and transforms). */ AZStd::vector mNodeInfos; /**< The per node info, shared between lods. */ @@ -992,7 +993,7 @@ namespace EMotionFX bool mDirtyFlag; /**< The dirty flag which indicates whether the user has made changes to the actor since the last file save operation. */ bool mUsedForVisualization; /**< Indicates if the actor is used for visualization specific things and is not used as a normal in-game actor. */ bool m_optimizeSkeleton; /**< Indicates if we should perform/ */ - + bool m_isReady = false; /**< If actor as well as its dependent files are fully loaded and initialized.*/ #if defined(EMFX_DEVELOPMENT_BUILD) bool mIsOwnedByRuntime; /**< Set if the actor is used/owned by the engine runtime. */ #endif // EMFX_DEVELOPMENT_BUILD diff --git a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp index 518db289e2..539b656754 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp @@ -68,6 +68,9 @@ namespace EMotionFX &actorSettings, ""); + assetData->m_emfxActor->Finalize(); + + // Clear out the EMFX raw asset data. assetData->ReleaseEMotionFXData(); if (!assetData->m_emfxActor) diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp index 982b62fbcf..f41ef165c8 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp @@ -154,17 +154,15 @@ namespace EMotionFX Actor* actor = m_configuration.m_actorAsset->GetActor(); if (actor) { - OnActorReady(actor); + CheckActorCreation(); } } ////////////////////////////////////////////////////////////////////////// ActorComponent::ActorComponent(const Configuration* configuration) : m_debugDrawRoot(false) - , m_sceneFinishSimHandler([this]( - [[maybe_unused]] AzPhysics::SceneHandle sceneHandle, - float fixedDeltatime - ) + , m_sceneFinishSimHandler([this]([[maybe_unused]] AzPhysics::SceneHandle sceneHandle, + float fixedDeltatime) { if (m_actorInstance) { @@ -192,18 +190,9 @@ namespace EMotionFX if (cfg.m_actorAsset.GetId().IsValid()) { - EMotionFX::ActorNotificationBus::Handler::BusDisconnect(); AZ::Data::AssetBus::Handler::BusDisconnect(); - EMotionFX::ActorNotificationBus::Handler::BusConnect(); AZ::Data::AssetBus::Handler::BusConnect(cfg.m_actorAsset.GetId()); cfg.m_actorAsset.QueueLoad(); - - // In case the asset was already loaded fully, create the actor directly. - if (cfg.m_actorAsset.IsReady() && - cfg.m_actorAsset->GetActor()) - { - cfg.m_actorAsset->GetActor()->LoadRemainingAssets(); - } } AZ::TickBus::Handler::BusConnect(); @@ -231,7 +220,6 @@ namespace EMotionFX LmbrCentral::AttachmentComponentNotificationBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); AZ::Data::AssetBus::Handler::BusDisconnect(); - EMotionFX::ActorNotificationBus::Handler::BusDisconnect(); DestroyActor(); m_configuration.m_actorAsset.Release(); @@ -314,28 +302,12 @@ namespace EMotionFX Actor* actor = m_configuration.m_actorAsset->GetActor(); AZ_Assert(m_configuration.m_actorAsset.IsReady() && actor, "Actor asset should be loaded and actor valid."); - actor->LoadRemainingAssets(); - actor->CheckFinalizeActor(); + CheckActorCreation(); } void ActorComponent::OnAssetReloaded(AZ::Data::Asset asset) { - DestroyActor(); - m_configuration.m_actorAsset = asset; - - const Actor* oldActor = m_configuration.m_actorAsset->GetActor(); - AZ::Data::Asset meshAsset = oldActor->GetMeshAsset(); - AZ::Data::Asset skinMetaAsset = oldActor->GetSkinMetaAsset(); - AZ::Data::Asset morphTargetMetaAsset = oldActor->GetMorphTargetMetaAsset(); - - m_configuration.m_actorAsset = asset; - Actor* newActor = m_configuration.m_actorAsset->GetActor(); - AZ_Assert(m_configuration.m_actorAsset.IsReady() && newActor, "Actor asset should be loaded and actor valid."); - - newActor->SetMeshAsset(meshAsset); - newActor->SetSkinMetaAsset(skinMetaAsset); - newActor->SetMorphTargetMetaAsset(morphTargetMetaAsset); - newActor->CheckFinalizeActor(); + OnAssetReady(asset); } bool ActorComponent::IsPhysicsSceneSimulationFinishEventConnected() const @@ -850,13 +822,5 @@ namespace EMotionFX m_actorInstance->RemoveAttachment(targetActorInstance); } } - - void ActorComponent::OnActorReady(Actor* actor) - { - if (m_configuration.m_actorAsset && m_configuration.m_actorAsset->GetActor() == actor) - { - CheckActorCreation(); - } - } } // namespace Integration } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h index 8188da19b4..4172ce63bc 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h @@ -44,7 +44,6 @@ namespace EMotionFX , private LmbrCentral::AttachmentComponentNotificationBus::Handler , private AzFramework::CharacterPhysicsDataRequestBus::Handler , private AzFramework::RagdollPhysicsNotificationBus::Handler - , private EMotionFX::ActorNotificationBus::Handler { public: AZ_COMPONENT(ActorComponent, "{BDC97E7F-A054-448B-A26F-EA2B5D78E377}"); @@ -168,9 +167,6 @@ namespace EMotionFX void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; int GetTickOrder() override; - // ActorNotificationBus::Handler - void OnActorReady(Actor* actor) override; - void CheckActorCreation(); void DestroyActor(); void CheckAttachToEntity(); diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp index d22bb0007f..7d5b7ade00 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp @@ -156,8 +156,6 @@ namespace EMotionFX ////////////////////////////////////////////////////////////////////////// void EditorActorComponent::Activate() { - EMotionFX::ActorNotificationBus::Handler::BusConnect(); - LoadActorAsset(); const AZ::EntityId entityId = GetEntityId(); @@ -186,8 +184,6 @@ namespace EMotionFX AZ::TickBus::Handler::BusDisconnect(); AZ::Data::AssetBus::Handler::BusDisconnect(); - EMotionFX::ActorNotificationBus::Handler::BusDisconnect(); - DestroyActorInstance(); m_actorAsset.Release(); } @@ -234,13 +230,6 @@ namespace EMotionFX AZ::Data::AssetBus::Handler::BusDisconnect(); AZ::Data::AssetBus::Handler::BusConnect(m_actorAsset.GetId()); m_actorAsset.QueueLoad(); - - // In case the asset was already loaded fully, create the actor directly. - if (m_actorAsset.IsReady() && - m_actorAsset->GetActor()) - { - m_actorAsset->GetActor()->LoadRemainingAssets(); - } } else { @@ -475,27 +464,13 @@ namespace EMotionFX Actor* actor = m_actorAsset->GetActor(); AZ_Assert(m_actorAsset.IsReady() && actor, "Actor asset should be loaded and actor valid."); - actor->LoadRemainingAssets(); - actor->CheckFinalizeActor(); + CheckActorCreation(); } void EditorActorComponent::OnAssetReloaded(AZ::Data::Asset asset) { DestroyActorInstance(); - - const Actor* oldActor = m_actorAsset->GetActor(); - AZ::Data::Asset meshAsset = oldActor->GetMeshAsset(); - AZ::Data::Asset skinMetaAsset = oldActor->GetSkinMetaAsset(); - AZ::Data::Asset morphTargetMetaAsset = oldActor->GetMorphTargetMetaAsset(); - - m_actorAsset = asset; - Actor* newActor = m_actorAsset->GetActor(); - AZ_Assert(m_actorAsset.IsReady() && newActor, "Actor asset should be loaded and actor valid."); - - newActor->SetMeshAsset(meshAsset); - newActor->SetSkinMetaAsset(skinMetaAsset); - newActor->SetMorphTargetMetaAsset(morphTargetMetaAsset); - newActor->CheckFinalizeActor(); + OnAssetReady(asset); } void EditorActorComponent::SetActorAsset(AZ::Data::Asset actorAsset) @@ -505,7 +480,7 @@ namespace EMotionFX Actor* actor = m_actorAsset->GetActor(); if (actor) { - OnActorReady(actor); + CheckActorCreation(); } } @@ -818,14 +793,6 @@ namespace EMotionFX return false; } - void EditorActorComponent::OnActorReady(Actor* actor) - { - if (m_actorAsset && m_actorAsset->GetActor() == actor) - { - CheckActorCreation(); - } - } - void EditorActorComponent::CheckActorCreation() { // Enable/disable debug drawing. diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h index 8ddd95c3b7..5dabbe4ada 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h @@ -45,7 +45,6 @@ namespace EMotionFX , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler , private AzToolsFramework::EditorVisibilityNotificationBus::Handler , public AzFramework::BoundsRequestBus::Handler - , private EMotionFX::ActorNotificationBus::Handler { public: AZ_EDITOR_COMPONENT(EditorActorComponent, "{A863EE1B-8CFD-4EDD-BA0D-1CEC2879AD44}"); @@ -142,9 +141,6 @@ namespace EMotionFX void OnAttached(AZ::EntityId targetId) override; void OnDetached(AZ::EntityId targetId) override; - // ActorNotificationBus::Handler - void OnActorReady(Actor* actor) override; - void CheckActorCreation(); void BuildGameEntity(AZ::Entity* gameEntity) override;