PrefabUndoTests.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Component/TransformBus.h>
  9. #include <AzCore/Component/ComponentApplicationBus.h>
  10. #include <AzFramework/Components/TransformComponent.h>
  11. #include <AzToolsFramework/Prefab/Undo/PrefabUndo.h>
  12. #include <Prefab/PrefabTestDomUtils.h>
  13. #include <Prefab/PrefabTestFixture.h>
  14. namespace UnitTest
  15. {
  16. using PrefabUndoTests = PrefabTestFixture;
  17. TEST_F(PrefabUndoTests, PrefabUndoEntityUpdate)
  18. {
  19. //create template with single entity
  20. AZ::Entity* newEntity = CreateEntity("New Entity", false);
  21. ASSERT_TRUE(newEntity);
  22. AZ::EntityId entityId = newEntity->GetId();
  23. //add a transform component for testing purposes
  24. newEntity->CreateComponent(AZ::EditorTransformComponentTypeId);
  25. newEntity->Init();
  26. newEntity->Activate();
  27. AZStd::unique_ptr<Instance> testInstance = m_prefabSystemComponent->CreatePrefab({ newEntity }, {}, "test/path");
  28. ASSERT_TRUE(testInstance);
  29. //get template id
  30. TemplateId templateId = testInstance->GetTemplateId();
  31. //create document with before change snapshot
  32. PrefabDom entityDomBeforeUpdate;
  33. m_instanceToTemplateInterface->GenerateEntityDomBySerializing(entityDomBeforeUpdate, *newEntity);
  34. float checkXValue = 0.0f;
  35. AZ::TransformBus::EventResult(checkXValue, entityId, &AZ::TransformInterface::GetWorldX);
  36. ASSERT_TRUE(0.0f == checkXValue);
  37. //update values on entity
  38. const float updatedXValue = 5.0f;
  39. AZ::TransformBus::Event(entityId, &AZ::TransformInterface::SetWorldX, updatedXValue);
  40. AZ::TransformBus::EventResult(checkXValue, entityId, &AZ::TransformInterface::GetWorldX);
  41. ASSERT_TRUE(updatedXValue == checkXValue);
  42. //create document with after change snapshot
  43. PrefabDom entityDomAfterUpdate;
  44. m_instanceToTemplateInterface->GenerateEntityDomBySerializing(entityDomAfterUpdate, *newEntity);
  45. //generate patch
  46. PrefabDom patch;
  47. m_instanceToTemplateInterface->GeneratePatch(patch, entityDomBeforeUpdate, entityDomAfterUpdate);
  48. //create undo node
  49. PrefabUndoEntityUpdate instanceEntityUndo("Entity Update Undo Node");
  50. instanceEntityUndo.Capture(entityDomBeforeUpdate, entityDomAfterUpdate, entityId);
  51. EntityAliasOptionalReference entityAliasRef = testInstance->GetEntityAlias(entityId);
  52. ASSERT_TRUE(entityAliasRef);
  53. EntityAlias entityAlias = entityAliasRef.value();
  54. //update template
  55. ASSERT_TRUE(m_instanceToTemplateInterface->PatchEntityInTemplate(patch, entityId));
  56. //undo change
  57. instanceEntityUndo.Undo();
  58. m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  59. // verify template updated correctly
  60. //instantiate second instance for checking if propagation works
  61. AZStd::unique_ptr<Instance> secondInstance = m_prefabSystemComponent->InstantiatePrefab(
  62. templateId, AZStd::nullopt,
  63. [](const AzToolsFramework::EntityList& entities)
  64. {
  65. AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
  66. &AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, entities);
  67. });
  68. ASSERT_TRUE(secondInstance);
  69. ValidateInstanceEntitiesActive(*secondInstance);
  70. //get the values from the transform on the entity
  71. AZ::EntityId secondNewEntity = secondInstance->GetEntityId(entityAlias);
  72. const float confirmXValue = 0.0f;
  73. float value = 10.0f;
  74. AZ::TransformBus::EventResult(value, secondNewEntity, &AZ::TransformInterface::GetWorldX);
  75. ASSERT_TRUE(confirmXValue == value);
  76. }
  77. TEST_F(PrefabUndoTests, PrefabUndoInstanceUpdate_AddEntity)
  78. {
  79. //create single entity
  80. AZ::Entity* newEntity = CreateEntity("New Entity", false);
  81. ASSERT_TRUE(newEntity);
  82. //create a first instance where the entity will be added
  83. AZStd::unique_ptr<Instance> testInstance = m_prefabSystemComponent->CreatePrefab({}, {}, "test/path");
  84. ASSERT_TRUE(testInstance);
  85. //get template id
  86. TemplateId templateId = testInstance->GetTemplateId();
  87. //create document with before change snapshot
  88. PrefabDom instanceDomBeforeUpdate;
  89. m_instanceToTemplateInterface->GenerateInstanceDomBySerializing(instanceDomBeforeUpdate, *testInstance);
  90. //add entity to instance
  91. testInstance->AddEntity(*newEntity);
  92. //create document with after change snapshot
  93. PrefabDom instanceDomAfterUpdate;
  94. m_instanceToTemplateInterface->GenerateInstanceDomBySerializing(instanceDomAfterUpdate, *testInstance);
  95. //generate patch
  96. PrefabDom patch;
  97. m_instanceToTemplateInterface->GeneratePatch(patch, instanceDomBeforeUpdate, instanceDomAfterUpdate);
  98. //create undo node
  99. PrefabUndoInstance instanceEntityAddUndo("Entity Update Undo Node");
  100. instanceEntityAddUndo.Capture(instanceDomBeforeUpdate, instanceDomAfterUpdate, templateId);
  101. //update template
  102. m_instanceToTemplateInterface->PatchTemplate(patch, templateId);
  103. //undo change
  104. instanceEntityAddUndo.Undo();
  105. m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  106. //get the entity id
  107. AZStd::vector<AZ::EntityId> entityIdVector;
  108. testInstance->GetEntityIds([&entityIdVector](const AZ::EntityId& entityId)
  109. {
  110. entityIdVector.push_back(entityId);
  111. return true;
  112. });
  113. // Entity count minimum is 1 due to container entity
  114. EXPECT_EQ(entityIdVector.size(), 1);
  115. }
  116. TEST_F(PrefabUndoTests, PrefabUndoInstanceUpdate_RemoveEntity)
  117. {
  118. //create single entity
  119. AZ::Entity* newEntity = CreateEntity("New Entity", false);
  120. ASSERT_TRUE(newEntity);
  121. AZ::EntityId entityId = newEntity->GetId();
  122. //create a first instance where the entity will be added
  123. AZStd::unique_ptr<Instance> testInstance = m_prefabSystemComponent->CreatePrefab({newEntity}, {}, "test/path");
  124. ASSERT_TRUE(testInstance);
  125. //get template id
  126. TemplateId templateId = testInstance->GetTemplateId();
  127. //create document with before change snapshot
  128. PrefabDom instanceDomBeforeUpdate;
  129. m_instanceToTemplateInterface->GenerateInstanceDomBySerializing(instanceDomBeforeUpdate, *testInstance);
  130. //detach entity from instance
  131. testInstance->DetachEntity(entityId);
  132. //create document with after change snapshot
  133. PrefabDom instanceDomAfterUpdate;
  134. m_instanceToTemplateInterface->GenerateInstanceDomBySerializing(instanceDomAfterUpdate, *testInstance);
  135. //generate patch
  136. PrefabDom patch;
  137. m_instanceToTemplateInterface->GeneratePatch(patch, instanceDomBeforeUpdate, instanceDomAfterUpdate);
  138. //create undo node
  139. PrefabUndoInstance instanceEntityRemoveUndo("Entity Update Undo Node");
  140. instanceEntityRemoveUndo.Capture(instanceDomBeforeUpdate, instanceDomAfterUpdate, templateId);
  141. //update template
  142. m_instanceToTemplateInterface->PatchTemplate(patch, templateId);
  143. //undo change
  144. instanceEntityRemoveUndo.Undo();
  145. m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  146. //get the entity id
  147. AZStd::vector<AZ::EntityId> entityIdVector;
  148. testInstance->GetEntityIds([&entityIdVector](const AZ::EntityId& entityId)
  149. {
  150. entityIdVector.push_back(entityId);
  151. return true;
  152. });
  153. // Entity count is container entity + our entity restored via the undo
  154. EXPECT_EQ(entityIdVector.size(), 2);
  155. }
  156. }