3
0

PrefabUndoEditEntityTests.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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 <Prefab/PrefabTestFixture.h>
  9. #include <AzToolsFramework/Entity/EditorEntityHelpers.h>
  10. #include <AzToolsFramework/Prefab/Undo/PrefabUndo.h>
  11. #include <AzToolsFramework/Prefab/Undo/PrefabUndoEntityOverrides.h>
  12. #include <Prefab/PrefabTestComponent.h>
  13. namespace UnitTest
  14. {
  15. using PrefabUndoEditEntityTests = PrefabTestFixture;
  16. TEST_F(PrefabUndoEditEntityTests, EditEntity)
  17. {
  18. const AZStd::string wheelEntityName = "Wheel";
  19. AZ::IO::Path engineRootPath;
  20. m_settingsRegistryInterface->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
  21. AZ::EntityId wheelEntityId = CreateEditorEntityUnderRoot(wheelEntityName);
  22. // Modify the transform component
  23. AZ::TransformBus::Event(wheelEntityId, &AZ::TransformInterface::SetWorldX, 10.0f);
  24. // Add a new comopnent
  25. AZ::Entity* wheelEntity = AzToolsFramework::GetEntityById(wheelEntityId);
  26. wheelEntity->Deactivate();
  27. wheelEntity->AddComponent(aznew PrefabTestComponent());
  28. wheelEntity->Activate();
  29. // Get after-state DOM value
  30. wheelEntity = AzToolsFramework::GetEntityById(wheelEntityId);
  31. EXPECT_TRUE(wheelEntity) << "Could not get entity object.";
  32. PrefabDom entityDomAfterEdit;
  33. m_instanceToTemplateInterface->GenerateEntityDomBySerializing(entityDomAfterEdit, *wheelEntity);
  34. EXPECT_TRUE(entityDomAfterEdit.IsObject()) << "Could not create after-state entity DOM.";
  35. // Get before-state DOM value
  36. AZStd::string entityAliasPath = m_instanceToTemplateInterface->GenerateEntityAliasPath(wheelEntityId);
  37. EXPECT_FALSE(entityAliasPath.empty());
  38. InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(wheelEntityId);
  39. TemplateId templateId = owningInstance->get().GetTemplateId();
  40. EXPECT_TRUE(templateId != InvalidTemplateId);
  41. PrefabDom& templateDom = m_prefabSystemComponent->FindTemplateDom(templateId);
  42. PrefabDomValue* entityDomInTemplate = PrefabDomPath(entityAliasPath.c_str()).Get(templateDom);
  43. EXPECT_TRUE(entityDomInTemplate) << "Could not retrieve entity DOM from template.";
  44. // Create an undo node
  45. PrefabUndoEntityUpdate undoNode("Undo Editing Entity");
  46. undoNode.Capture(*entityDomInTemplate, entityDomAfterEdit, wheelEntityId);
  47. // Redo
  48. undoNode.Redo();
  49. PropagateAllTemplateChanges();
  50. ASSERT_FLOAT_EQ(10.0f, wheelEntity->GetTransform()->GetWorldX());
  51. ASSERT_TRUE(wheelEntity->FindComponent<PrefabTestComponent>());
  52. // Undo
  53. undoNode.Undo();
  54. PropagateAllTemplateChanges();
  55. ASSERT_FLOAT_EQ(0.0f, wheelEntity->GetTransform()->GetWorldX());
  56. ASSERT_FALSE(wheelEntity->FindComponent<PrefabTestComponent>());
  57. // Redo
  58. undoNode.Redo();
  59. PropagateAllTemplateChanges();
  60. ASSERT_FLOAT_EQ(10.0f, wheelEntity->GetTransform()->GetWorldX());
  61. ASSERT_TRUE(wheelEntity->FindComponent<PrefabTestComponent>());
  62. }
  63. TEST_F(PrefabUndoEditEntityTests, EditEntityAsOverride)
  64. {
  65. PrefabOverridePublicInterface* overrideInterface = AZ::Interface<PrefabOverridePublicInterface>::Get();
  66. EXPECT_TRUE(overrideInterface) << "Could not get the override public interface.";
  67. const AZStd::string carPrefabName = "Car";
  68. const AZStd::string wheelEntityName = "Wheel";
  69. AZ::IO::Path engineRootPath;
  70. m_settingsRegistryInterface->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
  71. AZ::IO::Path carPrefabFilepath = engineRootPath / carPrefabName;
  72. AZ::EntityId wheelEntityId = CreateEditorEntityUnderRoot(wheelEntityName);
  73. AZ::EntityId carContainerId = CreateEditorPrefab(carPrefabFilepath, { wheelEntityId });
  74. EntityAlias wheelEntityAlias = FindEntityAliasInInstance(carContainerId, wheelEntityName);
  75. EXPECT_FALSE(wheelEntityAlias.empty());
  76. InstanceOptionalReference levelRootInstance = m_instanceEntityMapperInterface->FindOwningInstance(GetRootContainerEntityId());
  77. EXPECT_TRUE(levelRootInstance.has_value());
  78. InstanceOptionalReference carInstance = m_instanceEntityMapperInterface->FindOwningInstance(carContainerId);
  79. EXPECT_TRUE(carInstance.has_value());
  80. // Retrieve the wheel entity object and entity id after adding to instance
  81. EntityOptionalReference wheelEntityRef = carInstance->get().GetEntity(wheelEntityAlias);
  82. EXPECT_TRUE(wheelEntityRef.has_value());
  83. AZ::Entity* wheelEntity = &(wheelEntityRef->get());
  84. wheelEntityId = wheelEntity->GetId();
  85. // Modify the transform component as override
  86. AZ::TransformBus::Event(wheelEntityId, &AZ::TransformInterface::SetWorldX, 10.0f);
  87. // Add a new comopnent as override
  88. wheelEntity->Deactivate();
  89. wheelEntity->AddComponent(aznew PrefabTestComponent());
  90. wheelEntity->Activate();
  91. // Create an undo node and redo
  92. PrefabUndoEntityOverrides undoNode("Undo Editing Entity As Override");
  93. undoNode.CaptureAndRedo({ wheelEntity }, carInstance->get(), levelRootInstance->get());
  94. PropagateAllTemplateChanges();
  95. ASSERT_TRUE(overrideInterface->AreOverridesPresent(wheelEntityId));
  96. ASSERT_FLOAT_EQ(10.0f, wheelEntity->GetTransform()->GetWorldX());
  97. ASSERT_TRUE(wheelEntity->FindComponent<PrefabTestComponent>());
  98. // Undo
  99. undoNode.Undo();
  100. PropagateAllTemplateChanges();
  101. ASSERT_FALSE(overrideInterface->AreOverridesPresent(wheelEntityId));
  102. ASSERT_FLOAT_EQ(0.0f, wheelEntity->GetTransform()->GetWorldX());
  103. ASSERT_FALSE(wheelEntity->FindComponent<PrefabTestComponent>());
  104. // Redo
  105. undoNode.Redo();
  106. PropagateAllTemplateChanges();
  107. ASSERT_TRUE(overrideInterface->AreOverridesPresent(wheelEntityId));
  108. ASSERT_FLOAT_EQ(10.0f, wheelEntity->GetTransform()->GetWorldX());
  109. ASSERT_TRUE(wheelEntity->FindComponent<PrefabTestComponent>());
  110. }
  111. TEST_F(PrefabUndoEditEntityTests, EditEntityAsOverrideOnAddEntityOverride)
  112. {
  113. // Level <-- focused
  114. // | Car
  115. // | Dummy
  116. // | Entity <-- add-entity override
  117. PrefabOverridePublicInterface* overrideInterface = AZ::Interface<PrefabOverridePublicInterface>::Get();
  118. EXPECT_TRUE(overrideInterface) << "Could not get the override public interface.";
  119. const AZStd::string carPrefabName = "Car";
  120. AZ::IO::Path engineRootPath;
  121. m_settingsRegistryInterface->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
  122. AZ::IO::Path carPrefabFilepath = engineRootPath / carPrefabName;
  123. AZ::EntityId tireEntityId = CreateEditorEntityUnderRoot("Dummy");
  124. AZ::EntityId carContainerId = CreateEditorPrefab(carPrefabFilepath, { tireEntityId });
  125. // Create a new entity as override under the car instance
  126. PrefabEntityResult createEntityResult = m_prefabPublicInterface->CreateEntity(carContainerId, AZ::Vector3());
  127. EXPECT_TRUE(createEntityResult.IsSuccess()) << "Could not add a wheel entity as override.";
  128. AZ::EntityId addedEntityId = createEntityResult.GetValue();
  129. AZ::Entity* addedEntity = AzToolsFramework::GetEntityById(addedEntityId);
  130. EXPECT_TRUE(addedEntity);
  131. InstanceOptionalReference levelRootInstance = m_instanceEntityMapperInterface->FindOwningInstance(GetRootContainerEntityId());
  132. EXPECT_TRUE(levelRootInstance.has_value());
  133. InstanceOptionalReference carInstance = m_instanceEntityMapperInterface->FindOwningInstance(carContainerId);
  134. EXPECT_TRUE(carInstance.has_value());
  135. // Modify the transform component as override
  136. AZ::TransformBus::Event(addedEntityId, &AZ::TransformInterface::SetWorldX, 10.0f);
  137. // Add a new comopnent as override
  138. addedEntity->Deactivate();
  139. addedEntity->AddComponent(aznew PrefabTestComponent());
  140. addedEntity->Activate();
  141. // Create an undo node and redo
  142. PrefabUndoEntityOverrides undoNode("Undo Editing Entity As Override");
  143. undoNode.CaptureAndRedo({ addedEntity }, carInstance->get(), levelRootInstance->get());
  144. PropagateAllTemplateChanges();
  145. ASSERT_TRUE(overrideInterface->AreOverridesPresent(addedEntityId));
  146. ASSERT_FLOAT_EQ(10.0f, addedEntity->GetTransform()->GetWorldX());
  147. ASSERT_TRUE(addedEntity->FindComponent<PrefabTestComponent>());
  148. // Undo
  149. undoNode.Undo();
  150. PropagateAllTemplateChanges();
  151. ASSERT_TRUE(overrideInterface->AreOverridesPresent(addedEntityId)); // The added entity itself is an override edit
  152. ASSERT_FLOAT_EQ(0.0f, addedEntity->GetTransform()->GetWorldX());
  153. ASSERT_FALSE(addedEntity->FindComponent<PrefabTestComponent>());
  154. // Redo
  155. undoNode.Redo();
  156. PropagateAllTemplateChanges();
  157. ASSERT_TRUE(overrideInterface->AreOverridesPresent(addedEntityId));
  158. ASSERT_FLOAT_EQ(10.0f, addedEntity->GetTransform()->GetWorldX());
  159. ASSERT_TRUE(addedEntity->FindComponent<PrefabTestComponent>());
  160. }
  161. } // namespace UnitTest