PrefabUpdateInstancesTests.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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 <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
  9. #include <AzToolsFramework/Prefab/PrefabDomUtils.h>
  10. #include <Prefab/PrefabTestComponent.h>
  11. #include <Prefab/PrefabTestDomUtils.h>
  12. #include <Prefab/PrefabTestFixture.h>
  13. namespace UnitTest
  14. {
  15. using PrefabUpdateInstancesTest = PrefabTestFixture;
  16. TEST_F(PrefabUpdateInstancesTest, PrefabUpdateInstances_UpdateEntityName_UpdateSucceeds)
  17. {
  18. // Create a Template from an Instance owning a single entity.
  19. const char* newEntityName = "New Entity";
  20. AZ::Entity* newEntity = CreateEntity(newEntityName);
  21. AddRequiredEditorComponents({ newEntity->GetId() });
  22. AZStd::unique_ptr<Instance> firstInstance = m_prefabSystemComponent->CreatePrefab({ newEntity }, {}, PrefabMockFilePath);
  23. ASSERT_TRUE(firstInstance);
  24. TemplateId newTemplateId = firstInstance->GetTemplateId();
  25. EXPECT_TRUE(newTemplateId != InvalidTemplateId);
  26. PrefabDom& templatePrefabDom = m_prefabSystemComponent->FindTemplateDom(newTemplateId);
  27. AZStd::vector<EntityAlias> entityAliases = firstInstance->GetEntityAliases();
  28. EXPECT_EQ(entityAliases.size(), 1);
  29. // Instantiate Instances and validate if all entities of each Template's Instance have the given entity names.
  30. const int numberOfInstances = 3;
  31. AZStd::vector<AZStd::unique_ptr<Instance>> instantiatedInstances;
  32. for (int i = 0; i < numberOfInstances; ++i)
  33. {
  34. instantiatedInstances.emplace_back(m_prefabSystemComponent->InstantiatePrefab(newTemplateId));
  35. ASSERT_TRUE(instantiatedInstances.back());
  36. EXPECT_EQ(instantiatedInstances.back()->GetTemplateId(), newTemplateId);
  37. }
  38. PrefabDomPath entityNamePath = PrefabTestDomUtils::GetPrefabDomEntityNamePath(entityAliases.front());
  39. const PrefabDomValue* entityNameValue =
  40. PrefabTestDomUtils::GetPrefabDomEntityName(templatePrefabDom, entityAliases.front());
  41. ASSERT_TRUE(entityNameValue != nullptr);
  42. PrefabTestDomUtils::ValidateInstances(newTemplateId, *entityNameValue, entityNamePath);
  43. // Update Template's PrefabDom with a new entity name.
  44. entityNamePath.Set(templatePrefabDom, "Updated Entity");
  45. // Update Template's Instances.
  46. m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
  47. const bool updateResult = m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  48. EXPECT_TRUE(updateResult);
  49. // Validate if all entities of each Template's Instance have the updated entity names.
  50. PrefabTestDomUtils::ValidateInstances(newTemplateId, *entityNameValue, entityNamePath);
  51. }
  52. TEST_F(PrefabUpdateInstancesTest, UpdatePrefabInstances_AddEntity_UpdateSucceeds)
  53. {
  54. // Create a Template from an Instance owning a single entity.
  55. AZ::Entity* entity1 = CreateEntity("Entity 1");
  56. AddRequiredEditorComponents({ entity1->GetId() });
  57. AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab({ entity1 }, {}, PrefabMockFilePath);
  58. TemplateId newTemplateId = newInstance->GetTemplateId();
  59. EXPECT_TRUE(newTemplateId != InvalidTemplateId);
  60. PrefabDom& newTemplateDom = m_prefabSystemComponent->FindTemplateDom(newTemplateId);
  61. AZStd::vector<EntityAlias> newTemplateEntityAliases = newInstance->GetEntityAliases();
  62. EXPECT_EQ(newTemplateEntityAliases.size(), 1);
  63. // Instantiate Instances and validate if all Instances have the entity.
  64. const int numberOfInstances = 3;
  65. AZStd::vector<AZStd::unique_ptr<Instance>> instantiatedInstances;
  66. for (int i = 0; i < numberOfInstances; ++i)
  67. {
  68. instantiatedInstances.emplace_back(m_prefabSystemComponent->InstantiatePrefab(newTemplateId));
  69. ASSERT_TRUE(instantiatedInstances.back());
  70. EXPECT_EQ(instantiatedInstances.back()->GetTemplateId(), newTemplateId);
  71. }
  72. PrefabTestDomUtils::ValidateEntitiesOfInstances(newTemplateId, newTemplateDom, newTemplateEntityAliases);
  73. // Add another entity to the Instance and use it to update the PrefabDom of Template.
  74. AZ::Entity* entity2 = CreateEntity("Entity 2");
  75. newInstance->AddEntity(*entity2);
  76. AddRequiredEditorComponents({ entity2->GetId() });
  77. newTemplateEntityAliases = newInstance->GetEntityAliases();
  78. EXPECT_EQ(newTemplateEntityAliases.size(), 2);
  79. PrefabDom updatedTemplateDom;
  80. ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newInstance, updatedTemplateDom));
  81. newTemplateDom.CopyFrom(updatedTemplateDom, newTemplateDom.GetAllocator());
  82. // Update Template's Instances and validate if all Instances have the new entity.
  83. m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
  84. const bool updateResult = m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  85. EXPECT_TRUE(updateResult);
  86. PrefabTestDomUtils::ValidateEntitiesOfInstances(newTemplateId, newTemplateDom, newTemplateEntityAliases);
  87. }
  88. TEST_F(PrefabUpdateInstancesTest, UpdatePrefabInstances_AddInstance_UpdateSucceeds)
  89. {
  90. // Create a Template with single entity.
  91. AZ::Entity* entity = CreateEntity("Entity");
  92. AddRequiredEditorComponents({ entity->GetId() });
  93. AZStd::unique_ptr<Instance> newNestedInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, NestedPrefabMockFilePath);
  94. TemplateId newNestedTemplateId = newNestedInstance->GetTemplateId();
  95. EXPECT_TRUE(newNestedTemplateId != InvalidTemplateId);
  96. EXPECT_EQ(newNestedInstance->GetEntityAliases().size(), 1);
  97. // Create an enclosing Template with 0 entities and 1 nested Instance.
  98. AZStd::unique_ptr<Instance> nestedInstance1 = m_prefabSystemComponent->InstantiatePrefab(newNestedTemplateId);
  99. AZStd::unique_ptr<Instance> newEnclosingInstance = m_prefabSystemComponent->CreatePrefab({}, MakeInstanceList(AZStd::move(nestedInstance1)), PrefabMockFilePath);
  100. TemplateId newEnclosingTemplateId = newEnclosingInstance->GetTemplateId();
  101. EXPECT_TRUE(newEnclosingTemplateId != InvalidTemplateId);
  102. PrefabDom& newEnclosingTemplateDom = m_prefabSystemComponent->FindTemplateDom(newEnclosingTemplateId);
  103. AZStd::vector<InstanceAlias> nestedInstanceAliases = newEnclosingInstance->GetNestedInstanceAliases(newNestedTemplateId);
  104. EXPECT_EQ(nestedInstanceAliases.size(), 1);
  105. // Instantiate enclosing Instances and validate if all enclosing Instances have the nested Instance.
  106. const int numberOfInstances = 3;
  107. AZStd::vector<AZStd::unique_ptr<Instance>> instantiatedInstances;
  108. for (int i = 0; i < numberOfInstances; ++i)
  109. {
  110. instantiatedInstances.emplace_back(m_prefabSystemComponent->InstantiatePrefab(newEnclosingTemplateId));
  111. ASSERT_TRUE(instantiatedInstances.back());
  112. EXPECT_EQ(instantiatedInstances.back()->GetTemplateId(), newEnclosingTemplateId);
  113. }
  114. PrefabTestDomUtils::ValidateNestedInstancesOfInstances(
  115. newEnclosingTemplateId, newEnclosingTemplateDom, nestedInstanceAliases);
  116. // Add another nested Instance to the enclosing Instance and use it to update the PrefabDom of Template.
  117. AZStd::unique_ptr<Instance> nestedInstance2 = m_prefabSystemComponent->InstantiatePrefab(newNestedTemplateId);
  118. newEnclosingInstance->AddInstance(AZStd::move(nestedInstance2));
  119. PrefabDom updatedTemplateDom;
  120. ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newEnclosingInstance, updatedTemplateDom));
  121. newEnclosingTemplateDom.CopyFrom(updatedTemplateDom, newEnclosingTemplateDom.GetAllocator());
  122. // Validate that there are 2 wheel Instances under the axle Instance
  123. nestedInstanceAliases = newEnclosingInstance->GetNestedInstanceAliases(newNestedTemplateId);
  124. EXPECT_EQ(nestedInstanceAliases.size(), 2);
  125. // Update axle Template's Instances and validate if all axle Instances have the new wheel Instance.
  126. m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newEnclosingTemplateId);
  127. const bool updateResult = m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  128. EXPECT_TRUE(updateResult);
  129. PrefabTestDomUtils::ValidateNestedInstancesOfInstances(
  130. newEnclosingTemplateId, newEnclosingTemplateDom, nestedInstanceAliases);
  131. }
  132. TEST_F(PrefabUpdateInstancesTest, UpdatePrefabInstances_AddComponent_UpdateSucceeds)
  133. {
  134. // Create a Template from an Instance owning a single entity.
  135. AZ::Entity* entity = CreateEntity("Entity");
  136. AddRequiredEditorComponents({ entity->GetId() });
  137. const int expectedComponentCount = 9;
  138. AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, PrefabMockFilePath);
  139. TemplateId newTemplateId = newInstance->GetTemplateId();
  140. PrefabDom& newTemplateDom = m_prefabSystemComponent->FindTemplateDom(newTemplateId);
  141. AZStd::vector<EntityAlias> newTemplateEntityAliases = newInstance->GetEntityAliases();
  142. ASSERT_EQ(newTemplateEntityAliases.size(), 1);
  143. // Validate that the entity has 9 components under it. All of them are added through AddRequiredEditorComponents().
  144. const PrefabDomValue* entityComponents =
  145. PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
  146. ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
  147. EXPECT_EQ(entityComponents->MemberCount(), expectedComponentCount);
  148. // Instantiate Instances and validate if all Instances have the entity.
  149. const int numberOfInstances = 3;
  150. AZStd::vector<AZStd::unique_ptr<Instance>> instantiatedInstances;
  151. for (int i = 0; i < numberOfInstances; ++i)
  152. {
  153. instantiatedInstances.emplace_back(m_prefabSystemComponent->InstantiatePrefab(newTemplateId));
  154. ASSERT_TRUE(instantiatedInstances.back());
  155. EXPECT_EQ(instantiatedInstances.back()->GetTemplateId(), newTemplateId);
  156. }
  157. PrefabTestDomUtils::ValidateEntitiesOfInstances(newTemplateId, newTemplateDom, newTemplateEntityAliases);
  158. // Add a component to the Instance and use it to update the PrefabDom of Template.
  159. PrefabTestComponent* prefabTestComponent = aznew PrefabTestComponent(true);
  160. entity->Deactivate();
  161. entity->AddComponent(prefabTestComponent);
  162. PrefabDom updatedDom;
  163. ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newInstance, updatedDom));
  164. newTemplateDom.CopyFrom(updatedDom, newTemplateDom.GetAllocator());
  165. // Validate that the entity now has 2 components under it.
  166. entityComponents = PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
  167. ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
  168. EXPECT_EQ(entityComponents->MemberCount(), expectedComponentCount + 1);
  169. // Extract the component id of the entity in Template and verify that it matches with the component id of the Instance.
  170. PrefabTestDomUtils::ValidateComponentsDomHasId(*entityComponents, prefabTestComponent->RTTI_GetTypeName(), prefabTestComponent->GetId());
  171. // Update Template's Instances and validate if all Instances have the new component under their entities.
  172. m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
  173. const bool updateResult = m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  174. EXPECT_TRUE(updateResult);
  175. PrefabTestDomUtils::ValidateInstances(newTemplateId, *entityComponents,
  176. PrefabTestDomUtils::GetPrefabDomComponentsPath(newTemplateEntityAliases.front()));
  177. }
  178. TEST_F(PrefabUpdateInstancesTest, UpdatePrefabInstances_DetachEntity_UpdateSucceeds)
  179. {
  180. // Create a Template from an Instance owning 2 entities.
  181. using namespace AzToolsFramework::Prefab;
  182. AZ::Entity* entity1 = CreateEntity("Entity 1");
  183. AZ::Entity* entity2 = CreateEntity("Entity 2");
  184. AddRequiredEditorComponents({ entity1->GetId(), entity2->GetId() });
  185. AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab(
  186. { entity1, entity2 },
  187. {},
  188. PrefabMockFilePath);
  189. TemplateId newTemplateId = newInstance->GetTemplateId();
  190. EXPECT_TRUE(newTemplateId != InvalidTemplateId);
  191. PrefabDom& newTemplateDom = m_prefabSystemComponent->FindTemplateDom(newTemplateId);
  192. AZStd::vector<EntityAlias> newTemplateEntityAliases = newInstance->GetEntityAliases();
  193. EXPECT_EQ(newTemplateEntityAliases.size(), 2);
  194. // Instantiate Instances and validate if all Instances have both entities.
  195. const int numberOfInstances = 3;
  196. AZStd::vector<AZStd::unique_ptr<Instance>> instantiatedInstances;
  197. for (int i = 0; i < numberOfInstances; ++i)
  198. {
  199. instantiatedInstances.emplace_back(m_prefabSystemComponent->InstantiatePrefab(newTemplateId));
  200. ASSERT_TRUE(instantiatedInstances.back());
  201. EXPECT_EQ(instantiatedInstances.back()->GetTemplateId(), newTemplateId);
  202. }
  203. PrefabTestDomUtils::ValidateEntitiesOfInstances(newTemplateId, newTemplateDom, newTemplateEntityAliases);
  204. // Remove an entity from the Instance and use the updated Instance to update the PrefabDom of Template.
  205. AZStd::unique_ptr<AZ::Entity> detachedEntity = newInstance->DetachEntity(entity1->GetId());
  206. ASSERT_TRUE(detachedEntity);
  207. EXPECT_EQ(detachedEntity->GetId(), entity1->GetId());
  208. newTemplateEntityAliases = newInstance->GetEntityAliases();
  209. EXPECT_EQ(newTemplateEntityAliases.size(), 1);
  210. PrefabDom updatedTemplateDom;
  211. ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newInstance, updatedTemplateDom));
  212. newTemplateDom.CopyFrom(updatedTemplateDom, newTemplateDom.GetAllocator());
  213. // Update Template's Instances and validate if all Instances have the remaining entity.
  214. m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
  215. const bool updateResult = m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  216. EXPECT_TRUE(updateResult);
  217. PrefabTestDomUtils::ValidateEntitiesOfInstances(newTemplateId, newTemplateDom, newTemplateEntityAliases);
  218. }
  219. TEST_F(PrefabUpdateInstancesTest, UpdatePrefabInstances_DetachNestedInstance_UpdateSucceeds)
  220. {
  221. // Create a Template with single entity.
  222. AZ::Entity* entity = CreateEntity("Entity");
  223. AddRequiredEditorComponents({ entity->GetId() });
  224. AZStd::unique_ptr<Instance> newNestedInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, NestedPrefabMockFilePath);
  225. TemplateId newNestedTemplateId = newNestedInstance->GetTemplateId();
  226. EXPECT_TRUE(newNestedTemplateId != InvalidTemplateId);
  227. EXPECT_EQ(newNestedInstance->GetEntityAliases().size(), 1);
  228. // Create an enclosing Template with 0 entities and 2 nested Instances.
  229. AZStd::unique_ptr<Instance> nestedInstance1 = m_prefabSystemComponent->InstantiatePrefab(newNestedTemplateId);
  230. AZStd::unique_ptr<Instance> nestedInstance2 = m_prefabSystemComponent->InstantiatePrefab(newNestedTemplateId);
  231. AZStd::unique_ptr<Instance> newEnclosingInstance = m_prefabSystemComponent->CreatePrefab(
  232. {},
  233. MakeInstanceList(AZStd::move(nestedInstance1), AZStd::move(nestedInstance2)),
  234. PrefabMockFilePath);
  235. TemplateId newEnclosingTemplateId = newEnclosingInstance->GetTemplateId();
  236. EXPECT_TRUE(newEnclosingTemplateId != InvalidTemplateId);
  237. PrefabDom& newEnclosingTemplateDom = m_prefabSystemComponent->FindTemplateDom(newEnclosingTemplateId);
  238. AZStd::vector<InstanceAlias> nestedInstanceAliases = newEnclosingInstance->GetNestedInstanceAliases(newNestedTemplateId);
  239. EXPECT_EQ(nestedInstanceAliases.size(), 2);
  240. // Instantiate enclosing Instances and validate if all enclosing Instances have both nested Instances.
  241. const int numberOfInstances = 3;
  242. AZStd::vector<AZStd::unique_ptr<Instance>> instantiatedInstances;
  243. for (int i = 0; i < numberOfInstances; ++i)
  244. {
  245. instantiatedInstances.emplace_back(m_prefabSystemComponent->InstantiatePrefab(newEnclosingTemplateId));
  246. ASSERT_TRUE(instantiatedInstances.back());
  247. EXPECT_EQ(instantiatedInstances.back()->GetTemplateId(), newEnclosingTemplateId);
  248. }
  249. PrefabTestDomUtils::ValidateNestedInstancesOfInstances(
  250. newEnclosingTemplateId, newEnclosingTemplateDom, nestedInstanceAliases);
  251. // Remove one nested Instance from the enclosing Instance
  252. // and use the updated enclosing Instance to update the PrefabDom of Template.
  253. AZStd::unique_ptr<Instance> detachedInstance = newEnclosingInstance->DetachNestedInstance(nestedInstanceAliases.front());
  254. ASSERT_TRUE(detachedInstance);
  255. m_prefabSystemComponent->RemoveLink(detachedInstance->GetLinkId());
  256. PrefabDom updatedTemplateDom;
  257. ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newEnclosingInstance, updatedTemplateDom));
  258. newEnclosingTemplateDom.CopyFrom(updatedTemplateDom, newEnclosingTemplateDom.GetAllocator());
  259. // Validate that there is only one nested Instances under the enclosing Instance.
  260. nestedInstanceAliases = newEnclosingInstance->GetNestedInstanceAliases(newNestedTemplateId);
  261. EXPECT_EQ(nestedInstanceAliases.size(), 1);
  262. // Update enclosing Template's Instances and validate if all enclosing Instances have the remaining nested Instances.
  263. m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newEnclosingTemplateId);
  264. const bool updateResult = m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  265. EXPECT_TRUE(updateResult);
  266. PrefabTestDomUtils::ValidateNestedInstancesOfInstances(
  267. newEnclosingTemplateId, newEnclosingTemplateDom, nestedInstanceAliases);
  268. }
  269. TEST_F(PrefabUpdateInstancesTest, UpdatePrefabInstances_RemoveComponent_UpdateSucceeds)
  270. {
  271. // Create a Template from an Instance owning a single entity with a prefabTestComponent.
  272. AZ::Entity* entity = CreateEntity("Entity");
  273. AddRequiredEditorComponents({ entity->GetId() });
  274. entity->Deactivate();
  275. PrefabTestComponent* prefabTestComponent = aznew PrefabTestComponent(true);
  276. entity->AddComponent(prefabTestComponent);
  277. entity->Activate();
  278. const int expectedComponentCount = 10;
  279. AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, PrefabMockFilePath);
  280. TemplateId newTemplateId = newInstance->GetTemplateId();
  281. PrefabDom& newTemplateDom = m_prefabSystemComponent->FindTemplateDom(newTemplateId);
  282. AZStd::vector<EntityAlias> newTemplateEntityAliases = newInstance->GetEntityAliases();
  283. ASSERT_EQ(newTemplateEntityAliases.size(), 1);
  284. // Validate that the entity has 10 components under it. 9 of them are added through AddRequiredEditorComponents().
  285. const PrefabDomValue* entityComponents =
  286. PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
  287. ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
  288. EXPECT_EQ(entityComponents->MemberCount(), expectedComponentCount);
  289. // Extract the component id of the entity in the Template and verify that it matches with the component id of the entity's component.
  290. PrefabTestDomUtils::ValidateComponentsDomHasId(
  291. *entityComponents, prefabTestComponent->RTTI_GetTypeName(), prefabTestComponent->GetId());
  292. // Instantiate Instances and validate if all Instances have the entity.
  293. const int numberOfInstances = 3;
  294. AZStd::vector<AZStd::unique_ptr<Instance>> instantiatedInstances;
  295. for (int i = 0; i < numberOfInstances; ++i)
  296. {
  297. instantiatedInstances.emplace_back(m_prefabSystemComponent->InstantiatePrefab(newTemplateId));
  298. ASSERT_TRUE(instantiatedInstances.back());
  299. EXPECT_EQ(instantiatedInstances.back()->GetTemplateId(), newTemplateId);
  300. }
  301. PrefabTestDomUtils::ValidateInstances(
  302. newTemplateId, *entityComponents, PrefabTestDomUtils::GetPrefabDomComponentsPath(newTemplateEntityAliases.front()));
  303. // Remove a component from the Instance's entity and use the Instance to update the PrefabDom of Template.
  304. entity->Deactivate();
  305. entity->RemoveComponent(prefabTestComponent);
  306. delete prefabTestComponent;
  307. entity->Activate();
  308. PrefabDom updatedDom;
  309. ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newInstance, updatedDom));
  310. newTemplateDom.CopyFrom(updatedDom, newTemplateDom.GetAllocator());
  311. // Validate that the entity only has 9 component under it.
  312. entityComponents = PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
  313. ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
  314. EXPECT_EQ(entityComponents->MemberCount(), expectedComponentCount - 1);
  315. // Update Template's Instances and validate if all Instances have no component under their entities.
  316. m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
  317. const bool updateResult = m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  318. EXPECT_TRUE(updateResult);
  319. PrefabTestDomUtils::ValidateEntitiesOfInstances(newTemplateId, newTemplateDom, newTemplateEntityAliases);
  320. }
  321. TEST_F(PrefabUpdateInstancesTest, UpdatePrefabInstances_ChangeComponentProperty_UpdateSucceeds)
  322. {
  323. // Create a Template from an Instance owning a single entity with a PrefabTestComponent.
  324. AZ::Entity* entity = CreateEntity("Entity");
  325. AddRequiredEditorComponents({ entity->GetId() });
  326. entity->Deactivate();
  327. PrefabTestComponent* prefabTestComponent = aznew PrefabTestComponent(true);
  328. entity->AddComponent(prefabTestComponent);
  329. entity->Activate();
  330. const int expectedComponentCount = 10;
  331. AZStd::unique_ptr<Instance> newInstance = m_prefabSystemComponent->CreatePrefab({ entity }, {}, PrefabMockFilePath);
  332. TemplateId newTemplateId = newInstance->GetTemplateId();
  333. PrefabDom& newTemplateDom = m_prefabSystemComponent->FindTemplateDom(newTemplateId);
  334. AZStd::vector<EntityAlias> newTemplateEntityAliases = newInstance->GetEntityAliases();
  335. ASSERT_EQ(newTemplateEntityAliases.size(), 1);
  336. // Validate that the entity has 10 components under it. 9 of them are added through AddRequiredEditorComponents.
  337. const PrefabDomValue* entityComponents =
  338. PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
  339. ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
  340. EXPECT_EQ(entityComponents->MemberCount(), expectedComponentCount);
  341. // Extract the component id of the entity in the Template and verify that it matches with the component id of the entity's component.
  342. PrefabTestDomUtils::ValidateComponentsDomHasId(
  343. *entityComponents, prefabTestComponent->RTTI_GetTypeName(), prefabTestComponent->GetId());
  344. // Instantiate Instances and validate if all Instances have the entity.
  345. const int numberOfInstances = 3;
  346. AZStd::vector<AZStd::unique_ptr<Instance>> instantiatedInstances;
  347. for (int i = 0; i < numberOfInstances; ++i)
  348. {
  349. instantiatedInstances.emplace_back(m_prefabSystemComponent->InstantiatePrefab(newTemplateId));
  350. ASSERT_TRUE(instantiatedInstances.back());
  351. EXPECT_EQ(instantiatedInstances.back()->GetTemplateId(), newTemplateId);
  352. }
  353. PrefabDomPath entityComponentsPath = PrefabTestDomUtils::GetPrefabDomComponentsPath(newTemplateEntityAliases.front());
  354. PrefabTestDomUtils::ValidateInstances(
  355. newTemplateId, *entityComponents, entityComponentsPath);
  356. // Change the bool property of the component from the Instance and use the Instance to update the PrefabDom of Template.
  357. prefabTestComponent->m_boolProperty = false;
  358. PrefabDom updatedDom;
  359. ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newInstance, updatedDom));
  360. newTemplateDom.CopyFrom(updatedDom, newTemplateDom.GetAllocator());
  361. // Validate that the value of the BoolProperty of the prefabTestComponent in the Template's DOM has changed.
  362. entityComponents = PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
  363. ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
  364. EXPECT_EQ(entityComponents->MemberCount(), expectedComponentCount);
  365. PrefabDomValueConstReference wheelEntityComponentValue =
  366. PrefabDomUtils::FindPrefabDomValue(*entityComponents, prefabTestComponent->RTTI_GetTypeName());
  367. ASSERT_TRUE(wheelEntityComponentValue);
  368. PrefabDomValueConstReference wheelEntityComponentBoolPropertyValue =
  369. PrefabDomUtils::FindPrefabDomValue(wheelEntityComponentValue->get(), PrefabTestDomUtils::BoolPropertyName);
  370. ASSERT_TRUE(wheelEntityComponentBoolPropertyValue.has_value() && wheelEntityComponentBoolPropertyValue->get() == false);
  371. // Update Template's Instances and validate if all Instances have no BoolProperty under their prefabTestComponents in entities.
  372. m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
  373. const bool updateResult = m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
  374. EXPECT_TRUE(updateResult);
  375. PrefabTestDomUtils::ValidateInstances(newTemplateId, *entityComponents, entityComponentsPath);
  376. }
  377. }