You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/EMotionFX/Code/Tests/MotionExtractionBusTests.cpp

146 lines
6.3 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Component/TransformBus.h>
#include <AzFramework/Components/TransformComponent.h>
#include <EMotionFX/Source/ActorManager.h>
#include <EMotionFX/Source/AnimGraphMotionNode.h>
#include <EMotionFX/Source/MotionSet.h>
#include <EMotionFX/Source/Motion.h>
#include <Integration/Components/ActorComponent.h>
#include <Integration/Components/AnimGraphComponent.h>
#include <Integration/MotionExtractionBus.h>
#include <Tests/Integration/EntityComponentFixture.h>
#include <Tests/TestAssetCode/ActorFactory.h>
#include <Tests/TestAssetCode/AnimGraphFactory.h>
#include <Tests/TestAssetCode/JackActor.h>
#include <Tests/TestAssetCode/TestActorAssets.h>
#include <Tests/TestAssetCode/TestMotionAssets.h>
namespace EMotionFX
{
class MotionExtractionTestBus
: Integration::MotionExtractionRequestBus::Handler
{
public:
MotionExtractionTestBus(AZ::EntityId entityId)
{
Integration::MotionExtractionRequestBus::Handler::BusConnect(entityId);
}
~MotionExtractionTestBus()
{
Integration::MotionExtractionRequestBus::Handler::BusDisconnect();
}
MOCK_METHOD2(ExtractMotion, void(const AZ::Vector3&, float));
};
class MotionExtractionBusTests
: public EntityComponentFixture
{
public:
void SetUp() override
{
EntityComponentFixture::SetUp();
m_entityId = AZ::EntityId(740216387);
m_entity = AZStd::make_unique<AZ::Entity>(m_entityId);
// Actor asset.
AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}");
AZStd::unique_ptr<Actor> actor = ActorFactory::CreateAndInit<JackNoMeshesActor>();
AZ::Data::Asset<Integration::ActorAsset> actorAsset = TestActorAssets::GetAssetFromActor(actorAssetId, AZStd::move(actor));
Integration::ActorComponent::Configuration actorConf;
actorConf.m_actorAsset = actorAsset;
m_entity->CreateComponent<AzFramework::TransformComponent>();
auto actorComponent = m_entity->CreateComponent<Integration::ActorComponent>(&actorConf);
auto animGraphComponent = m_entity->CreateComponent<Integration::AnimGraphComponent>();
m_entity->Init();
// Anim graph asset.
AZ::Data::AssetId animGraphAssetId("{37629818-5166-4B96-83F5-5818B6A1F449}");
animGraphComponent->SetAnimGraphAssetId(animGraphAssetId);
AZ::Data::Asset<Integration::AnimGraphAsset> animGraphAsset = AZ::Data::AssetManager::Instance().CreateAsset<Integration::AnimGraphAsset>(animGraphAssetId);
AZStd::unique_ptr<TwoMotionNodeAnimGraph> motionNodeAnimGraph = AnimGraphFactory::Create<TwoMotionNodeAnimGraph>();
m_animGraph = motionNodeAnimGraph.get();
motionNodeAnimGraph.release();
animGraphAsset.GetAs<Integration::AnimGraphAsset>()->SetData(m_animGraph);
EXPECT_EQ(animGraphAsset.IsReady(), true) << "Anim graph asset is not ready yet.";
animGraphComponent->OnAssetReady(animGraphAsset);
// Motion set asset.
AZ::Data::AssetId motionSetAssetId("{224BFF5F-D0AD-4216-9CEF-42F419CC6265}");
animGraphComponent->SetMotionSetAssetId(motionSetAssetId);
AZ::Data::Asset<Integration::MotionSetAsset> motionSetAsset = AZ::Data::AssetManager::Instance().CreateAsset<Integration::MotionSetAsset>(motionSetAssetId);
m_motionSet = aznew MotionSet("motionSet");
Motion* motion = TestMotionAssets::GetJackWalkForward();
AddMotionEntry(motion, "jack_walk_forward_aim_zup");
m_animGraph->GetMotionNodeA()->AddMotionId("jack_walk_forward_aim_zup");
motionSetAsset.GetAs<Integration::MotionSetAsset>()->SetData(new MotionSet());
EXPECT_EQ(motionSetAsset.IsReady(), true) << "Motion set asset is not ready yet.";
animGraphComponent->OnAssetReady(motionSetAsset);
m_entity->Activate();
// Actor component
actorComponent->SetActorAsset(actorAsset);
}
void AddMotionEntry(Motion* motion, const AZStd::string& motionId)
{
m_motion = motion;
EMotionFX::MotionSet::MotionEntry* newMotionEntry = aznew EMotionFX::MotionSet::MotionEntry();
newMotionEntry->SetMotion(m_motion);
m_motionSet->AddMotionEntry(newMotionEntry);
m_motionSet->SetMotionEntryId(newMotionEntry, motionId);
}
void TearDown() override
{
EntityComponentFixture::TearDown();
m_motionSet->Clear();
m_motion->Destroy();
delete m_motionSet;
}
public:
AZ::EntityId m_entityId;
AZStd::unique_ptr<AZ::Entity> m_entity;
MotionSet* m_motionSet = nullptr;
Motion* m_motion = nullptr;
TwoMotionNodeAnimGraph* m_animGraph = nullptr;
};
TEST_F(MotionExtractionBusTests, ExtractMotionTests)
{
MotionExtractionTestBus testBus(m_entityId);
const float timeDelta = 0.5f;
const ActorManager* actorManager = GetEMotionFX().GetActorManager();
const ActorInstance* actorInstance = actorManager->GetActorInstance(0);
bool hasCustomMotionExtractionController = Integration::MotionExtractionRequestBus::FindFirstHandler(m_entityId) != nullptr;
EXPECT_TRUE(hasCustomMotionExtractionController) << "MotionExtractionBus is not found.";
AZ::Transform currentTransform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(currentTransform, m_entityId, &AZ::TransformBus::Events::GetWorldTM);
const AZ::Vector3 actorInstancePosition = actorInstance->GetWorldSpaceTransform().m_position;
const AZ::Vector3 positionDelta = actorInstancePosition - currentTransform.GetTranslation();
EXPECT_CALL(testBus, ExtractMotion(testing::_, testing::_));
Integration::MotionExtractionRequestBus::Event(m_entityId, &Integration::MotionExtractionRequestBus::Events::ExtractMotion, positionDelta, timeDelta);
}
} // end namespace EMotionFX