PrefabUndoAddEntityTests.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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/PrefabUndoAddEntityTestFixture.h>
  9. namespace UnitTest
  10. {
  11. using PrefabUndoAddEntityTests = PrefabUndoAddEntityTestFixture;
  12. TEST_F(PrefabUndoAddEntityTests, PrefabUndoAddEntity_AddEntityUnderFocusedInstance)
  13. {
  14. // Create a car instance as our current focused instance.
  15. AZStd::unique_ptr<Instance> focusedCarInstancePtr =
  16. m_prefabSystemComponent->CreatePrefab({}, {}, "test/path");
  17. ASSERT_TRUE(focusedCarInstancePtr);
  18. Instance& focusedCarInstance = *focusedCarInstancePtr;
  19. // Create another car instance to later help verify if propagation works.
  20. AZStd::unique_ptr<Instance> secondCarInstancePtr =
  21. m_prefabSystemComponent->InstantiatePrefab(focusedCarInstance.GetTemplateId());
  22. ASSERT_TRUE(secondCarInstancePtr);
  23. Instance& secondCarInstance = *secondCarInstancePtr;
  24. InstanceList carInstances{focusedCarInstance, secondCarInstance};
  25. // Create a car entity and add it under our car instance.
  26. const AZStd::string carEntityName = "Car";
  27. const EntityAlias carEntityAlias = CreateEntity(carEntityName, focusedCarInstance);
  28. ASSERT_FALSE(carEntityAlias.empty());
  29. // Create undo/redo node for adding the car entity under the car instance.
  30. PrefabUndoAddEntity undoAddCarEntityNode = CreatePrefabUndoAddEntityNode(
  31. carEntityAlias, focusedCarInstance, "Undo Adding Car Entity");
  32. size_t expectedEntityCount = 0;
  33. // Adding the car entity under the car instance by redoing with our undo node and doing template propagation.
  34. undoAddCarEntityNode.Redo();
  35. PropagateAllTemplateChanges();
  36. ++expectedEntityCount;
  37. for (auto& instance : carInstances)
  38. {
  39. ValidateNewEntityUnderInstance(instance, carEntityAlias, carEntityName, expectedEntityCount);
  40. }
  41. // Create an axle entity and add it under the car entity.
  42. const AZStd::string axleEntityName = "Axle";
  43. const EntityAlias axleEntityAlias = CreateEntity(axleEntityName, focusedCarInstance, carEntityAlias);
  44. ASSERT_FALSE(axleEntityAlias.empty());
  45. // Create undo/redo node for adding the axle entity under the car entity.
  46. PrefabUndoAddEntity undoAddAxleEntityNode = CreatePrefabUndoAddEntityNode(
  47. axleEntityAlias, focusedCarInstance, "Undo Adding Axle Entity", carEntityAlias);
  48. // Adding the axle entity under the car entity by redoing with our undo node and doing template propagation.
  49. undoAddAxleEntityNode.Redo();
  50. PropagateAllTemplateChanges();
  51. ++expectedEntityCount;
  52. for (auto& instance : carInstances)
  53. {
  54. ValidateNewEntityUnderParentEntity(instance, carEntityAlias, carEntityName,
  55. axleEntityAlias, axleEntityName, expectedEntityCount);
  56. }
  57. // Create a wheel entity and add it under the axle entity.
  58. const AZStd::string wheelEntityName = "Wheel";
  59. const EntityAlias wheelEntityAlias = CreateEntity(wheelEntityName, focusedCarInstance, axleEntityAlias);
  60. ASSERT_FALSE(wheelEntityAlias.empty());
  61. // Create undo/redo node for adding the wheel entity under the axle entity.
  62. PrefabUndoAddEntity undoAddWheelEntityNode = CreatePrefabUndoAddEntityNode(
  63. wheelEntityAlias, focusedCarInstance, "Undo Adding Wheel Entity", axleEntityAlias);
  64. // Adding the wheel entity under the axle entity by redoing with our undo node and doing template propagation.
  65. undoAddWheelEntityNode.Redo();
  66. PropagateAllTemplateChanges();
  67. ++expectedEntityCount;
  68. for (auto& instance : carInstances)
  69. {
  70. ValidateNewEntityUnderParentEntity(instance, axleEntityAlias, axleEntityName,
  71. wheelEntityAlias, wheelEntityName, expectedEntityCount);
  72. }
  73. // Undo adding the wheel entity under the axle entity.
  74. undoAddWheelEntityNode.Undo();
  75. PropagateAllTemplateChanges();
  76. --expectedEntityCount;
  77. for (auto& instance : carInstances)
  78. {
  79. ValidateNewEntityNotUnderParentEntity(instance, axleEntityAlias, axleEntityName,
  80. wheelEntityAlias, expectedEntityCount);
  81. }
  82. // Undo adding the axle entity under the car entity.
  83. undoAddAxleEntityNode.Undo();
  84. PropagateAllTemplateChanges();
  85. --expectedEntityCount;
  86. for (auto& instance : carInstances)
  87. {
  88. ValidateNewEntityNotUnderParentEntity(instance, carEntityAlias, carEntityName,
  89. axleEntityAlias, expectedEntityCount);
  90. }
  91. // Undo adding the car entity under the car instance.
  92. undoAddCarEntityNode.Undo();
  93. PropagateAllTemplateChanges();
  94. --expectedEntityCount;
  95. for (auto& instance : carInstances)
  96. {
  97. ValidateNewEntityNotUnderInstance(instance, carEntityAlias, expectedEntityCount);
  98. }
  99. // Redo all adding entity operations.
  100. undoAddCarEntityNode.Redo();
  101. PropagateAllTemplateChanges();
  102. ++expectedEntityCount;
  103. undoAddAxleEntityNode.Redo();
  104. PropagateAllTemplateChanges();
  105. ++expectedEntityCount;
  106. undoAddWheelEntityNode.Redo();
  107. PropagateAllTemplateChanges();
  108. ++expectedEntityCount;
  109. for (auto& instance : carInstances)
  110. {
  111. ValidateNewEntityUnderParentEntity(instance, axleEntityAlias, axleEntityName,
  112. wheelEntityAlias, wheelEntityName, expectedEntityCount);
  113. }
  114. }
  115. TEST_F(PrefabUndoAddEntityTests, PrefabUndoAddEntity_AddEntityUnderUnfocusedInstance)
  116. {
  117. // Create a wheel instance.
  118. AZStd::unique_ptr<Instance> wheelInstancePtr =
  119. m_prefabSystemComponent->CreatePrefab({}, {}, "test/path/wheel");
  120. ASSERT_TRUE(wheelInstancePtr);
  121. Instance& leftWheelInstanceBeforePropagation = *wheelInstancePtr;
  122. const InstanceAlias leftWheelInstanceAlias = wheelInstancePtr->GetInstanceAlias();
  123. // Create another wheel instance to be added under an axle instance later.
  124. AZStd::unique_ptr<Instance> secondWheelInstancePtr =
  125. m_prefabSystemComponent->InstantiatePrefab(wheelInstancePtr->GetTemplateId());
  126. ASSERT_TRUE(secondWheelInstancePtr);
  127. const InstanceAlias rightWheelInstanceAlias = secondWheelInstancePtr->GetInstanceAlias();
  128. // Create an axle instance which includes two wheel instances under it.
  129. AZStd::unique_ptr<Instance> axleInstancePtr =
  130. m_prefabSystemComponent->CreatePrefab({},
  131. MakeInstanceList(AZStd::move(wheelInstancePtr), AZStd::move(secondWheelInstancePtr)),
  132. "test/path/axle");
  133. ASSERT_TRUE(axleInstancePtr);
  134. const InstanceAlias axleInstanceAlias = axleInstancePtr->GetInstanceAlias();
  135. // Create a car instance which includes one axle instance under it.
  136. AZStd::unique_ptr<Instance> carInstancePtr =
  137. m_prefabSystemComponent->CreatePrefab({},
  138. MakeInstanceList(AZStd::move(axleInstancePtr)),
  139. "test/path/car");
  140. ASSERT_TRUE(carInstancePtr);
  141. Instance& focusedCarInstance = *carInstancePtr;
  142. // Create a left wheel entity and add it under our left wheel instance.
  143. const AZStd::string leftWheelEntityName = "LeftWheel";
  144. const EntityAlias leftWheelEntityAlias = CreateEntity(leftWheelEntityName, leftWheelInstanceBeforePropagation);
  145. ASSERT_FALSE(leftWheelEntityAlias.empty());
  146. // Create undo/redo node for adding the left wheel entity under the left wheel instance.
  147. PrefabUndoAddEntityAsOverride undoAddLeftWheelEntityNode = CreatePrefabUndoAddEntityAsOverrideNode(
  148. leftWheelEntityAlias, leftWheelInstanceBeforePropagation, focusedCarInstance, "Undo Adding Left Wheel Entity");
  149. size_t expectedLeftWheelInstanceEntityCount = 0;
  150. size_t expectedRightWheelInstanceEntityCount = 0;
  151. // Adding the left wheel entity under the left wheel instance by redoing with our undo node and doing template propagation.
  152. undoAddLeftWheelEntityNode.Redo();
  153. PropagateAllTemplateChanges();
  154. ++expectedLeftWheelInstanceEntityCount;
  155. auto findAxleInstanceResult = focusedCarInstance.FindNestedInstance(axleInstanceAlias);
  156. ASSERT_TRUE(findAxleInstanceResult.has_value());
  157. Instance& axleInstance = findAxleInstanceResult->get();
  158. auto findLeftWheelInstanceResult = axleInstance.FindNestedInstance(leftWheelInstanceAlias);
  159. ASSERT_TRUE(findLeftWheelInstanceResult.has_value());
  160. Instance& leftWheelInstance = findLeftWheelInstanceResult->get();
  161. auto findRightWheelInstanceResult = axleInstance.FindNestedInstance(rightWheelInstanceAlias);
  162. ASSERT_TRUE(findRightWheelInstanceResult.has_value());
  163. Instance& rightWheelInstance = findRightWheelInstanceResult->get();
  164. // We should see the left wheel entity be added under left wheel instance.
  165. ValidateNewEntityUnderInstance(
  166. leftWheelInstance, leftWheelEntityAlias, leftWheelEntityName, expectedLeftWheelInstanceEntityCount);
  167. // The focused instance is the car instance, which is the ancestor instance of
  168. // the owning instance of our new wheel entity (left wheel instance).
  169. // After propagation, we should see the new wheel entity has been added under
  170. // left wheel instance, not right wheel instance.
  171. ValidateNewEntityNotUnderInstance(
  172. rightWheelInstance, leftWheelEntityAlias, expectedRightWheelInstanceEntityCount);
  173. // Create a tire entity and add it under our left wheel entity.
  174. const AZStd::string tireEntityName = "Tire";
  175. const EntityAlias tireEntityAlias = CreateEntity(tireEntityName, leftWheelInstance, leftWheelEntityAlias);
  176. ASSERT_FALSE(tireEntityAlias.empty());
  177. // Create undo/redo node for adding the tire entity under the left wheel entity.
  178. PrefabUndoAddEntityAsOverride undoAddTireEntityNode = CreatePrefabUndoAddEntityAsOverrideNode(
  179. tireEntityAlias, leftWheelInstance, focusedCarInstance, "Undo Adding Tire Entity", leftWheelEntityAlias);
  180. // Adding the tire entity under the left wheel entity by redoing with our undo node and doing template propagation.
  181. undoAddTireEntityNode.Redo();
  182. PropagateAllTemplateChanges();
  183. ++expectedLeftWheelInstanceEntityCount;
  184. ValidateNewEntityUnderParentEntity(leftWheelInstance, leftWheelEntityAlias, leftWheelEntityName,
  185. tireEntityAlias, tireEntityName, expectedLeftWheelInstanceEntityCount);
  186. ValidateNewEntityNotUnderInstance(rightWheelInstance, tireEntityAlias, expectedRightWheelInstanceEntityCount);
  187. // Undo adding the tire entity under the left wheel entity.
  188. undoAddTireEntityNode.Undo();
  189. PropagateAllTemplateChanges();
  190. --expectedLeftWheelInstanceEntityCount;
  191. ValidateNewEntityNotUnderParentEntity(leftWheelInstance, leftWheelEntityAlias, leftWheelEntityName,
  192. tireEntityAlias, expectedLeftWheelInstanceEntityCount);
  193. // Undo adding the left wheel entity under the left wheel instance.
  194. undoAddLeftWheelEntityNode.Undo();
  195. PropagateAllTemplateChanges();
  196. --expectedLeftWheelInstanceEntityCount;
  197. InstanceList wheelInstances = { leftWheelInstance, rightWheelInstance };
  198. for (auto& instance : wheelInstances)
  199. {
  200. ValidateNewEntityNotUnderInstance(instance, leftWheelEntityAlias, expectedLeftWheelInstanceEntityCount);
  201. }
  202. // Redo all adding entity operations.
  203. undoAddLeftWheelEntityNode.Redo();
  204. PropagateAllTemplateChanges();
  205. ++expectedLeftWheelInstanceEntityCount;
  206. undoAddTireEntityNode.Redo();
  207. PropagateAllTemplateChanges();
  208. ++expectedLeftWheelInstanceEntityCount;
  209. ValidateNewEntityUnderParentEntity(leftWheelInstance, leftWheelEntityAlias, leftWheelEntityName,
  210. tireEntityAlias, tireEntityName, expectedLeftWheelInstanceEntityCount);
  211. ValidateNewEntityUnderInstance(leftWheelInstance, leftWheelEntityAlias, leftWheelEntityName,
  212. expectedLeftWheelInstanceEntityCount);
  213. ValidateNewEntityNotUnderInstance(rightWheelInstance, leftWheelEntityAlias, expectedRightWheelInstanceEntityCount);
  214. ValidateNewEntityNotUnderInstance(rightWheelInstance, tireEntityAlias, expectedRightWheelInstanceEntityCount);
  215. // Create a right wheel entity and add it under our right wheel instance.
  216. const AZStd::string rightWheelEntityName = "RightWheel";
  217. const EntityAlias rightWheelEntityAlias = CreateEntity(rightWheelEntityName, rightWheelInstance);
  218. ASSERT_FALSE(rightWheelEntityAlias.empty());
  219. // Create undo/redo node for adding the right wheel entity under the right wheel instance.
  220. PrefabUndoAddEntityAsOverride undoAddRightWheelEntityNode = CreatePrefabUndoAddEntityAsOverrideNode(
  221. rightWheelEntityAlias, rightWheelInstance, focusedCarInstance, "Undo Adding Right Wheel Entity");
  222. // Adding the right wheel entity under the right wheel instance by redoing with our undo node and doing template propagation.
  223. undoAddRightWheelEntityNode.Redo();
  224. PropagateAllTemplateChanges();
  225. ++expectedRightWheelInstanceEntityCount;
  226. ValidateNewEntityUnderInstance(rightWheelInstance, rightWheelEntityAlias, rightWheelEntityName,
  227. expectedRightWheelInstanceEntityCount);
  228. ValidateNewEntityNotUnderInstance(leftWheelInstance, rightWheelEntityAlias, expectedLeftWheelInstanceEntityCount);
  229. // Undo adding the right wheel entity under the right wheel instance.
  230. undoAddRightWheelEntityNode.Undo();
  231. PropagateAllTemplateChanges();
  232. --expectedRightWheelInstanceEntityCount;
  233. ValidateNewEntityNotUnderInstance(rightWheelInstance, rightWheelEntityAlias, expectedRightWheelInstanceEntityCount);
  234. ValidateNewEntityNotUnderInstance(leftWheelInstance, rightWheelEntityAlias, expectedLeftWheelInstanceEntityCount);
  235. }
  236. }