123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- /*
- * 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 <Prefab/PrefabTestFixture.h>
- #include <AzCore/Component/TransformBus.h>
- #include <AzToolsFramework/Entity/EditorEntityHelpers.h>
- #include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
- #include <AzToolsFramework/Prefab/PrefabDomUtils.h>
- #include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
- #include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
- #include <AzToolsFramework/ToolsComponents/TransformComponent.h>
- #include <Prefab/PrefabTestComponent.h>
- #include <Prefab/PrefabTestDomUtils.h>
- namespace UnitTest
- {
- PrefabTestToolsApplication::PrefabTestToolsApplication(AZStd::string appName)
- : ToolsTestApplication(AZStd::move(appName))
- {
- }
- void PrefabTestFixture::SetUpEditorFixtureImpl()
- {
- // Acquire the system entity
- AZ::Entity* systemEntity = GetApplication()->FindEntity(AZ::SystemEntityId);
- EXPECT_TRUE(systemEntity);
- m_prefabSystemComponent = systemEntity->FindComponent<AzToolsFramework::Prefab::PrefabSystemComponent>();
- EXPECT_TRUE(m_prefabSystemComponent);
- m_prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
- EXPECT_TRUE(m_prefabLoaderInterface);
- m_prefabPublicInterface = AZ::Interface<PrefabPublicInterface>::Get();
- EXPECT_TRUE(m_prefabPublicInterface);
- m_instanceEntityMapperInterface = AZ::Interface<InstanceEntityMapperInterface>::Get();
- EXPECT_TRUE(m_instanceEntityMapperInterface);
- m_instanceUpdateExecutorInterface = AZ::Interface<InstanceUpdateExecutorInterface>::Get();
- EXPECT_TRUE(m_instanceUpdateExecutorInterface);
- m_instanceToTemplateInterface = AZ::Interface<InstanceToTemplateInterface>::Get();
- EXPECT_TRUE(m_instanceToTemplateInterface);
- m_prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
- EXPECT_TRUE(m_prefabEditorEntityOwnershipInterface);
- m_settingsRegistryInterface = AZ::SettingsRegistry::Get();
- EXPECT_TRUE(m_settingsRegistryInterface);
- // Have all instances cache their DOM for testing purposes.
- Instance::s_DomCachingEnabledDefault = true;
- // This is for calling CreateEditorRepresentation that adds required editor components.
- AzToolsFramework::EditorRequestBus::Handler::BusConnect();
- GetApplication()->RegisterComponentDescriptor(PrefabTestComponent::CreateDescriptor());
- GetApplication()->RegisterComponentDescriptor(PrefabNonEditorComponent::CreateDescriptor());
- GetApplication()->RegisterComponentDescriptor(PrefabTestComponentWithUnReflectedTypeMember::CreateDescriptor());
- // Gets undo stack.
- AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
- m_undoStack, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetUndoStack);
- AZ_Assert(m_undoStack, "Failed to look up undo stack from tools application");
- // This ensures that the flag (if root prefab is assigned) in prefab editor entity ownership service is set to true.
- // Public prefab operations like "create prefab" will fail if the flag is off.
- CreateRootPrefab();
- }
- void PrefabTestFixture::TearDownEditorFixtureImpl()
- {
- m_undoStack = nullptr;
- AzToolsFramework::EditorRequestBus::Handler::BusDisconnect();
- }
- AZStd::unique_ptr<ToolsTestApplication> PrefabTestFixture::CreateTestApplication()
- {
- return AZStd::make_unique<PrefabTestToolsApplication>("PrefabTestApplication");
- }
- void PrefabTestFixture::CreateRootPrefab()
- {
- m_prefabEditorEntityOwnershipInterface->CreateNewLevelPrefab("UnitTestRoot.prefab", "");
- InstanceOptionalReference rootInstance = m_prefabEditorEntityOwnershipInterface->GetRootPrefabInstance();
- ASSERT_TRUE(rootInstance.has_value());
-
- EntityOptionalReference rootContainerEntity = rootInstance->get().GetContainerEntity();
- ASSERT_TRUE(rootContainerEntity.has_value());
- if (rootContainerEntity->get().GetState() == AZ::Entity::State::Constructed)
- {
- rootContainerEntity->get().Init();
- }
- // Focus on root prefab instance.
- auto* prefabFocusPublicInterface = AZ::Interface<PrefabFocusPublicInterface>::Get();
- EXPECT_TRUE(prefabFocusPublicInterface != nullptr);
- PrefabFocusOperationResult focusResult = prefabFocusPublicInterface->FocusOnOwningPrefab(
- rootContainerEntity->get().GetId());
- EXPECT_TRUE(focusResult.IsSuccess());
- }
- void PrefabTestFixture::PropagateAllTemplateChanges()
- {
- m_prefabSystemComponent->OnSystemTick();
- }
- AZ::EntityId PrefabTestFixture::CreateEditorEntityUnderRoot(const AZStd::string& entityName)
- {
- return CreateEditorEntity(entityName, GetRootContainerEntityId());
- }
- AZ::EntityId PrefabTestFixture::CreateEditorEntity(const AZStd::string& entityName, AZ::EntityId parentId)
- {
- PrefabEntityResult createResult = m_prefabPublicInterface->CreateEntity(parentId, AZ::Vector3());
- AZ_Assert(createResult.IsSuccess(), "CreateEditorEntity - Failed to create entity %s. Error: %s",
- entityName.c_str(), createResult.GetError().c_str());
- // Verify new entity.
- AZ::EntityId newEntityId = createResult.GetValue();
- EXPECT_TRUE(newEntityId.IsValid());
- AZ::Entity* newEntity = AzToolsFramework::GetEntityById(newEntityId);
- EXPECT_TRUE(newEntity != nullptr);
- newEntity->SetName(entityName);
- m_prefabPublicInterface->GenerateUndoNodesForEntityChangeAndUpdateCache(newEntityId, m_undoStack->GetTop());
- PropagateAllTemplateChanges();
- return newEntityId;
- }
- AZ::EntityId PrefabTestFixture::CreateEditorPrefab(AZ::IO::PathView filePath, const AzToolsFramework::EntityIdList& entityIds)
- {
- // New prefab instance is reparent under the common root entity of the input entities.
- CreatePrefabResult createResult = m_prefabPublicInterface->CreatePrefabInMemory(entityIds, filePath);
- AZ_Assert(createResult.IsSuccess(), "CreateEditorPrefab - Failed to create prefab %s. Error: %s",
- AZStd::string(filePath.Native()).c_str(),
- createResult.GetError().c_str());
- // Verify new container entity.
- AZ::EntityId prefabContainerId = createResult.GetValue();
- EXPECT_TRUE(prefabContainerId.IsValid());
- AZ::Entity* prefabContainerEntity = AzToolsFramework::GetEntityById(prefabContainerId);
- EXPECT_TRUE(prefabContainerEntity != nullptr);
- PropagateAllTemplateChanges();
- return prefabContainerId;
- }
- AZ::EntityId PrefabTestFixture::InstantiateEditorPrefab(AZ::IO::PathView filePath, AZ::EntityId parentId)
- {
- InstantiatePrefabResult instantiateResult = m_prefabPublicInterface->InstantiatePrefab(
- filePath.Native(), parentId, AZ::Vector3());
- AZ_Assert(instantiateResult.IsSuccess(), "InstantiateEditorPrefab - Failed to instantiate prefab %s. Error: %s",
- AZStd::string(filePath.Native()).c_str(),
- instantiateResult.GetError().c_str());
- // Verify new container entity.
- AZ::EntityId prefabContainerId = instantiateResult.GetValue();
- EXPECT_TRUE(prefabContainerId.IsValid());
- AZ::Entity* prefabContainerEntity = AzToolsFramework::GetEntityById(prefabContainerId);
- EXPECT_TRUE(prefabContainerEntity != nullptr);
-
- PropagateAllTemplateChanges();
- return prefabContainerId;
- }
- AZ::Entity* PrefabTestFixture::CreateEntity(const AZStd::string& entityName, bool shouldActivate)
- {
- AZ::Entity* newEntity = aznew AZ::Entity(entityName);
-
- if (shouldActivate)
- {
- newEntity->Init();
- newEntity->Activate();
- }
- return newEntity;
- }
- AZ::EntityId PrefabTestFixture::GetRootContainerEntityId()
- {
- auto rootInstance = m_prefabEditorEntityOwnershipInterface->GetRootPrefabInstance();
- EXPECT_TRUE(rootInstance.has_value());
- AZ::EntityId rootContainerId = rootInstance->get().GetContainerEntityId();
- EXPECT_TRUE(rootContainerId.IsValid());
- return rootContainerId;
- }
- void PrefabTestFixture::CompareInstances(const AzToolsFramework::Prefab::Instance& instanceA,
- const AzToolsFramework::Prefab::Instance& instanceB, bool shouldCompareLinkIds, bool shouldCompareContainerEntities)
- {
- AzToolsFramework::Prefab::TemplateId templateAId = instanceA.GetTemplateId();
- AzToolsFramework::Prefab::TemplateId templateBId = instanceB.GetTemplateId();
- ASSERT_TRUE(templateAId != AzToolsFramework::Prefab::InvalidTemplateId);
- ASSERT_TRUE(templateBId != AzToolsFramework::Prefab::InvalidTemplateId);
- EXPECT_EQ(templateAId, templateBId);
- AzToolsFramework::Prefab::TemplateReference templateA =
- m_prefabSystemComponent->FindTemplate(templateAId);
- ASSERT_TRUE(templateA.has_value());
- AzToolsFramework::Prefab::PrefabDom prefabDomA;
- ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(instanceA, prefabDomA));
- AzToolsFramework::Prefab::PrefabDom prefabDomB;
- ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(instanceB, prefabDomB));
- // Validate that both instances match when serialized.
- PrefabTestDomUtils::ComparePrefabDoms(prefabDomA, prefabDomB, shouldCompareLinkIds, shouldCompareContainerEntities);
- // Validate that the serialized instances match the shared template when serialized
- // Note: We do not compare the link ids. The template DOM is not supposed to have this member.
- PrefabTestDomUtils::ComparePrefabDoms(templateA->get().GetPrefabDom(), prefabDomB, false, shouldCompareContainerEntities);
- }
- void PrefabTestFixture::DeleteInstances(const InstanceList& instancesToDelete)
- {
- for (Instance* instanceToDelete : instancesToDelete)
- {
- ASSERT_TRUE(instanceToDelete);
- delete instanceToDelete;
- instanceToDelete = nullptr;
- }
- }
- EntityAlias PrefabTestFixture::FindEntityAliasInInstance(
- AZ::EntityId containerEntityId, const AZStd::string& entityName)
- {
- auto owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(containerEntityId);
- EXPECT_TRUE(owningInstance.has_value());
- EntityAlias foundEntityAlias = "";
- owningInstance->get().GetEntities(
- [&foundEntityAlias, &owningInstance, &entityName](AZStd::unique_ptr<AZ::Entity>& entity)
- {
- if (entity->GetName() == entityName)
- {
- auto entityAlias = owningInstance->get().GetEntityAlias(entity->GetId());
- EXPECT_TRUE(entityAlias.has_value()) << "FindEntityAliasInInstance - Retrieved entity alias is null.";
- foundEntityAlias = entityAlias->get();
- return false;
- }
- return true;
- });
- return foundEntityAlias;
- }
- InstanceAlias PrefabTestFixture::FindNestedInstanceAliasInInstance(
- AZ::EntityId containerEntityId, const AZStd::string& nestedContainerEntityName)
- {
- auto owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(containerEntityId);
- EXPECT_TRUE(owningInstance.has_value());
- InstanceAlias foundInstanceAlias = "";
- owningInstance->get().GetNestedInstances(
- [&foundInstanceAlias, &nestedContainerEntityName](AZStd::unique_ptr<Instance>& nestedInstance)
- {
- auto nestedContainerEntity = nestedInstance->GetContainerEntity();
- EXPECT_TRUE(nestedContainerEntity.has_value());
- if (nestedContainerEntity->get().GetName() == nestedContainerEntityName)
- {
- foundInstanceAlias = nestedInstance->GetInstanceAlias();
- return;
- }
- });
- return foundInstanceAlias;
- }
- void PrefabTestFixture::RenameEntity(AZ::EntityId entityId, const AZStd::string& newName)
- {
- ASSERT_FALSE(newName.empty()) << "Cannot rename an entity to empty string.";
- AZ::Entity* entityToRename = AzToolsFramework::GetEntityById(entityId);
- ASSERT_TRUE(entityToRename != nullptr) << "Cannot rename a null entity.";
- entityToRename->SetName(newName);
- m_prefabPublicInterface->GenerateUndoNodesForEntityChangeAndUpdateCache(entityId, m_undoStack->GetTop());
- PropagateAllTemplateChanges();
- }
- void PrefabTestFixture::ValidateEntityUnderInstance(
- AZ::EntityId containerEntityId, const EntityAlias& entityAlias, const AZStd::string& entityName)
- {
- auto owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(containerEntityId);
- EXPECT_TRUE(owningInstance.has_value());
- auto entity = owningInstance->get().GetEntity(entityAlias);
- ASSERT_TRUE(entity.has_value());
- ASSERT_EQ(entity->get().GetName(), entityName);
- }
- void PrefabTestFixture::ValidateEntityNotUnderInstance(
- AZ::EntityId containerEntityId, const EntityAlias& entityAlias)
- {
- auto owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(containerEntityId);
- EXPECT_TRUE(owningInstance.has_value());
- auto entity = owningInstance->get().GetEntity(entityAlias);
- ASSERT_FALSE(entity.has_value());
- }
- void PrefabTestFixture::ValidateNestedInstanceUnderInstance(
- AZ::EntityId containerEntityId, const InstanceAlias& nestedInstanceAlias)
- {
- auto owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(containerEntityId);
- EXPECT_TRUE(owningInstance.has_value());
- auto nestedInstance = owningInstance->get().FindNestedInstance(nestedInstanceAlias);
- ASSERT_TRUE(nestedInstance.has_value());
- }
- void PrefabTestFixture::ValidateNestedInstanceNotUnderInstance(
- AZ::EntityId containerEntityId, const InstanceAlias& nestedInstanceAlias)
- {
- auto owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(containerEntityId);
- EXPECT_TRUE(owningInstance.has_value());
- auto nestedInstance = owningInstance->get().FindNestedInstance(nestedInstanceAlias);
- ASSERT_FALSE(nestedInstance.has_value());
- }
- void PrefabTestFixture::ValidateInstanceEntitiesActive(Instance& instance)
- {
- AZStd::vector<AZ::EntityId> entityIdVector;
- instance.GetAllEntityIdsInHierarchy([&entityIdVector](AZ::EntityId entityId) {
- entityIdVector.push_back(entityId);
- return true;
- });
- for (AZ::EntityId entityId : entityIdVector)
- {
- AZ::Entity* entityInInstance = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(entityInInstance, &AZ::ComponentApplicationBus::Events::FindEntity, entityId);
- ASSERT_TRUE(entityInInstance);
- EXPECT_EQ(entityInInstance->GetState(), AZ::Entity::State::Active);
- }
- }
- void PrefabTestFixture::ProcessDeferredUpdates()
- {
- // Force a prefab propagation for updates that are deferred to the next tick.
- m_prefabSystemComponent->OnSystemTick();
- }
- void PrefabTestFixture::Undo()
- {
- m_undoStack->Undo();
- ProcessDeferredUpdates();
- }
- void PrefabTestFixture::Redo()
- {
- m_undoStack->Redo();
- ProcessDeferredUpdates();
- }
- void PrefabTestFixture::AddRequiredEditorComponents(const AzToolsFramework::EntityIdList& entityIds)
- {
- for (AZ::EntityId entityId : entityIds)
- {
- AZ::Entity* entity = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, entityId);
- EXPECT_TRUE(entity != nullptr) << "The entity to be added required editor components is nullptr.";
- entity->Deactivate();
- AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
- &AzToolsFramework::EditorEntityContextRequests::AddRequiredComponents, *entity);
- entity->Activate();
- }
- }
- // EditorRequestBus
- void PrefabTestFixture::CreateEditorRepresentation(AZ::Entity* entity)
- {
- if (!entity)
- {
- EXPECT_TRUE(false) << "Cannot call CreateEditorRepresentation for a null entity.";
- return;
- }
- AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
- &AzToolsFramework::EditorEntityContextRequestBus::Events::AddRequiredComponents, *entity);
- }
- } // namespace UnitTest
|