EMFX - Refactor the emfx actor asset loading. (#1101)

Refactor emfx asset loading. The mesh asset, skinMetaAsset and morphTargetMeta asset are part of the dependency.
main
rhongAMZ 5 years ago committed by GitHub
parent 64872e024e
commit fe98c34f50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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)

@ -52,7 +52,7 @@ namespace EMotionFX
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ActorGroupExporter, AZ::SceneAPI::SceneCore::ExportingComponent>()->Version(1);
serializeContext->Class<ActorGroupExporter, AZ::SceneAPI::SceneCore::ExportingComponent>()->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<AZ::RPI::ModelAsset>(),
azrtti_typeid<AZ::RPI::SkinMetaAsset>(),
azrtti_typeid<AZ::RPI::MorphTargetMetaAsset>()
};
for (const AZ::Data::AssetType& assetDependency : assetDependencyList)
{
AZStd::optional<AZ::SceneAPI::Events::ExportProduct> 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<AZ::SceneAPI::Events::ExportProduct> ActorGroupExporter::GetFirstProductByType(
const ActorGroupExportContext& context, AZ::Data::AssetType type)
{
const AZStd::vector<AZ::SceneAPI::Events::ExportProduct>& 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

@ -14,6 +14,7 @@
#include <AzCore/std/optional.h>
#include <EMotionFX/Source/AutoRegisteredActor.h>
#include <SceneAPI/SceneCore/Components/ExportingComponent.h>
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
#include <Integration/System/SystemCommon.h>
@ -44,6 +45,8 @@ namespace EMotionFX
//! Get the mesh asset id to which the actor is linked to by default.
AZStd::optional<AZ::Data::AssetId> GetMeshAssetId(const ActorGroupExportContext& context) const;
static AZStd::optional<AZ::SceneAPI::Events::ExportProduct> GetFirstProductByType(
const ActorGroupExportContext& context, AZ::Data::AssetType type);
AutoRegisteredActor m_actor;
AZStd::vector<AZStd::string> m_actorMaterialReferences;

@ -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<AZ::Data::AssetData> 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<AZStd::recursive_mutex> 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<AZ::RPI::ModelAsset>(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<AZ::RPI::SkinMetaAsset>(
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<AZ::RPI::MorphTargetMetaAsset>(
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<AZ::Data::AssetData> 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<AZStd::recursive_mutex> 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<AZ::RPI::ModelAsset>(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<AZ::RPI::SkinMetaAsset>(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<AZ::RPI::MorphTargetMetaAsset>(morphTargetMetaAssetId, AZ::Data::AssetLoadBehavior::Default);
}
}
}
Node* Actor::FindMeshJoint(const AZ::Data::Asset<AZ::RPI::ModelLodAsset>& lodModelAsset) const
{
const AZStd::array_view<AZ::RPI::ModelLodAsset::Mesh>& sourceMeshes = lodModelAsset->GetMeshes();
@ -2843,7 +2781,7 @@ namespace EMotionFX
return mSkeleton->GetNode(0);
}
void Actor::ConstructMeshes(const AZStd::unordered_map<AZ::u16, AZ::u16>& 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<EMotionFX::SkinningInfoVertexAttributeLayer*>(vertexAttributeLayer);
EMotionFX::SkinningInfoVertexAttributeLayer* skinLayer =
static_cast<EMotionFX::SkinningInfoVertexAttributeLayer*>(vertexAttributeLayer);
const AZ::u32 numOrgVerts = skinLayer->GetNumAttributes();
AZStd::set<AZ::u32> localJointIndices = skinLayer->CalcLocalJointIndices(numOrgVerts);
const AZ::u32 numLocalJoints = static_cast<AZ::u32>(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<LODLevel>& lodLevels = m_meshLodData.m_lodLevels;
const AZStd::array_view<AZ::Data::Asset<AZ::RPI::ModelLodAsset>>& lodAssets = m_meshAsset->GetLodAssets();
const size_t numLODLevels = lodAssets.size();

@ -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<AZ::RPI::ModelAsset>& GetMeshAsset() const { return m_meshAsset; }
const AZ::Data::Asset<AZ::RPI::SkinMetaAsset>& GetSkinMetaAsset() const { return m_skinMetaAsset; }
const AZ::Data::Asset<AZ::RPI::MorphTargetMetaAsset>& GetMorphTargetMetaAsset() const { return m_morphTargetMetaAsset; }
const AZStd::unordered_map<AZ::u16, AZ::u16>& GetSkinToSkeletonIndexMap() const { return m_skinToSkeletonIndexMap; }
void SetMeshAsset(AZ::Data::Asset<AZ::RPI::ModelAsset> asset) { m_meshAsset = asset; }
void SetSkinMetaAsset(AZ::Data::Asset<AZ::RPI::SkinMetaAsset> asset) { m_skinMetaAsset = asset; }
void SetMorphTargetMetaAsset(AZ::Data::Asset<AZ::RPI::MorphTargetMetaAsset> 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<AZ::u32>& includedJointIndices);
// AZ::Data::AssetBus::Handler
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
AZStd::unordered_map<AZ::u16, AZ::u16> ConstructSkinToSkeletonIndexMap(const AZ::Data::Asset<AZ::RPI::SkinMetaAsset>& skinMetaAsset);
void ConstructMeshes(const AZStd::unordered_map<AZ::u16, AZ::u16>& 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<AZ::RPI::ModelLodAsset>& lodModelAsset) const;
void SetActorReady();
bool m_isReady = false;
Skeleton* mSkeleton; /**< The skeleton, containing the nodes and bind pose. */
MCore::Array<Dependency> mDependencies; /**< The dependencies on other actors (shared meshes and transforms). */
AZStd::vector<NodeInfo> 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

@ -68,6 +68,9 @@ namespace EMotionFX
&actorSettings,
"");
assetData->m_emfxActor->Finalize();
// Clear out the EMFX raw asset data.
assetData->ReleaseEMotionFXData();
if (!assetData->m_emfxActor)

@ -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<AZ::Data::AssetData> asset)
{
DestroyActor();
m_configuration.m_actorAsset = asset;
const Actor* oldActor = m_configuration.m_actorAsset->GetActor();
AZ::Data::Asset<AZ::RPI::ModelAsset> meshAsset = oldActor->GetMeshAsset();
AZ::Data::Asset<AZ::RPI::SkinMetaAsset> skinMetaAsset = oldActor->GetSkinMetaAsset();
AZ::Data::Asset<AZ::RPI::MorphTargetMetaAsset> 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

@ -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();

@ -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<AZ::Data::AssetData> asset)
{
DestroyActorInstance();
const Actor* oldActor = m_actorAsset->GetActor();
AZ::Data::Asset<AZ::RPI::ModelAsset> meshAsset = oldActor->GetMeshAsset();
AZ::Data::Asset<AZ::RPI::SkinMetaAsset> skinMetaAsset = oldActor->GetSkinMetaAsset();
AZ::Data::Asset<AZ::RPI::MorphTargetMetaAsset> 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> 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.

@ -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;

Loading…
Cancel
Save