/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include namespace EMotionFX { namespace Integration { class TestRenderActor : public RenderActor { public: AZ_RTTI(TestRenderActor, "{560849A4-7767-4654-8C61-EDA9A0059BE1}", RenderActor) AZ_CLASS_ALLOCATOR(TestRenderActor, EMotionFXAllocator, 0) TestRenderActor(ActorAsset* actorAsset) : RenderActor() , m_actorAsset(actorAsset) { } public: ActorAsset* m_actorAsset = nullptr; }; class TestRenderActorInstance : public RenderActorInstance { public: AZ_RTTI(TestRenderActorInstance, "{8F5CD404-9661-4A71-9583-EB8E66F3C0E8}", RenderActorInstance) AZ_CLASS_ALLOCATOR(TestRenderActorInstance, EMotionFXAllocator, 0) TestRenderActorInstance(AZ::EntityId entityId, const EMotionFXPtr& actorInstance, const AZ::Data::Asset& asset, const ActorAsset::MaterialList& materialPerLOD, SkinningMethod skinningMethod, const AZ::Transform& worldTransform) : RenderActorInstance(asset, actorInstance.get(), entityId) , m_entityId(entityId) , m_actorAsset(asset) , m_actorInstance(actorInstance) , m_materialPerLOD(materialPerLOD) , m_skinningMethod(skinningMethod) , m_worldTransform(worldTransform) { } MOCK_METHOD1(OnTick, void(float)); MOCK_METHOD1(DebugDraw, void(const EMotionFX::ActorRenderFlags&)); MOCK_CONST_METHOD0(IsVisible, bool()); MOCK_METHOD1(SetIsVisible, void(bool)); MOCK_METHOD1(SetMaterials, void(const ActorAsset::MaterialList&)); MOCK_METHOD0(UpdateBounds, void()); MOCK_METHOD0(GetWorldBounds, AZ::Aabb()); MOCK_METHOD0(GetLocalBounds, AZ::Aabb()); public: AZ::EntityId m_entityId; AZ::Data::Asset m_actorAsset; EMotionFXPtr m_actorInstance; ActorAsset::MaterialList m_materialPerLOD; SkinningMethod m_skinningMethod = SkinningMethod::Linear; AZ::Transform m_worldTransform = AZ::Transform::CreateIdentity(); }; class TestRenderBackend : public RenderBackend { public: AZ_RTTI(TestRenderBackend, "{22CC2C55-8019-4302-8DFD-E08E0CA48114}", RenderBackend) AZ_CLASS_ALLOCATOR(TestRenderBackend, EMotionFXAllocator, 0) RenderActor* CreateActor(ActorAsset* actorAsset) override { return aznew TestRenderActor(actorAsset); } RenderActorInstance* CreateActorInstance(AZ::EntityId entityId, const EMotionFXPtr& actorInstance, const AZ::Data::Asset& asset, const ActorAsset::MaterialList& materialPerLOD, SkinningMethod skinningMethod, const AZ::Transform& worldTransform) override { return aznew TestRenderActorInstance(entityId, actorInstance, asset, materialPerLOD, skinningMethod, worldTransform); } }; class RenderBackendManagerFixture : public SystemComponentFixture { public: void SetUp() override { SystemComponentFixture::SetUp(); EXPECT_NE(AZ::Interface::Get(), nullptr); } public: TestRenderBackend* m_renderBackend = nullptr; }; TEST_F(RenderBackendManagerFixture, AdjustRenderBackend) { RenderBackendManager* renderBackendManager = AZ::Interface::Get(); EXPECT_NE(renderBackendManager, nullptr); m_renderBackend = aznew TestRenderBackend(); AZ::Interface::Get()->SetRenderBackend(m_renderBackend); RenderBackend* renderBackend = renderBackendManager->GetRenderBackend(); EXPECT_NE(renderBackend, nullptr); EXPECT_EQ(renderBackend->RTTI_GetType(), azrtti_typeid()); } class RenderBackendActorTestComponent : public AZ::Component { public: AZ_COMPONENT(RenderBackendActorTestComponent, "{699DE64B-ADD1-4B27-AC54-3D041AF82938}"); RenderBackendActorTestComponent() : AZ::Component() { } static void Reflect(AZ::ReflectContext* context) { auto* serializeContext = azrtti_cast(context); if (serializeContext) { serializeContext->Class() ->Version(1); } } void Activate() override { m_actorInstance = m_actorAsset->CreateInstance(GetEntity()); EXPECT_NE(m_actorInstance, nullptr); RenderBackend* renderBackend = AZ::Interface::Get()->GetRenderBackend(); m_renderActorInstance.reset(renderBackend->CreateActorInstance(GetEntityId(), m_actorInstance, m_actorAsset, /*materialPerLOD=*/{}, SkinningMethod::Linear, /*transform=*/{})); } void Deactivate() override { m_actorAsset.Release(); m_actorInstance.reset(); m_renderActorInstance.reset(); } public: AZ::Data::Asset m_actorAsset; ActorAsset::ActorInstancePtr m_actorInstance; AZStd::unique_ptr m_renderActorInstance; }; TEST_F(RenderBackendManagerFixture, RenderActorComponentTest) { m_app.RegisterComponentDescriptor(RenderBackendActorTestComponent::CreateDescriptor()); RenderBackendManager* renderBackendManager = AZ::Interface::Get(); ASSERT_NE(renderBackendManager, nullptr); m_renderBackend = aznew TestRenderBackend(); AZ::Interface::Get()->SetRenderBackend(m_renderBackend); RenderBackend* renderBackend = renderBackendManager->GetRenderBackend(); ASSERT_NE(renderBackend, nullptr); EXPECT_EQ(renderBackend->RTTI_GetType(), azrtti_typeid()); AZ::Data::AssetId actorAssetId("{D568F319-49E9-47BA-9E1C-24F949EF28DD}"); AZStd::unique_ptr actor = ActorFactory::CreateAndInit(); AZ::Data::Asset actorAsset = TestActorAssets::GetAssetFromActor(actorAssetId, AZStd::move(actor)); // Create render actor. AZStd::unique_ptr renderActor(renderBackend->CreateActor(actorAsset.Get())); EXPECT_EQ(renderActor->RTTI_GetType(), azrtti_typeid()); TestRenderActor* testRenderActor = azdynamic_cast(renderActor.get()); ASSERT_NE(testRenderActor, nullptr); // Create entity with a test actor component (that creates a render actor instance). AZ::EntityId entityId(42); auto gameEntity = AZStd::make_unique(); gameEntity->SetId(entityId); auto testActorComponent = gameEntity->CreateComponent(); testActorComponent->m_actorAsset = actorAsset; gameEntity->Init(); gameEntity->Activate(); EXPECT_EQ(testActorComponent->m_actorAsset, actorAsset); EXPECT_NE(testActorComponent->m_actorInstance, nullptr); TestRenderActorInstance* renderActorInstance = azdynamic_cast(testActorComponent->m_renderActorInstance.get()); ASSERT_NE(renderActorInstance, nullptr); EXPECT_EQ(renderActorInstance->RTTI_GetType(), azrtti_typeid()); EXPECT_EQ(renderActorInstance->m_entityId, entityId); EXPECT_EQ(renderActorInstance->m_actorInstance, testActorComponent->m_actorInstance); EXPECT_EQ(renderActorInstance->GetActor(), actorAsset->GetActor()); } } // namespace Integration } // namespace EMotionFX