ComponentModeSwitcherTests.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  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 <Tests/ComponentModeTestDoubles.h>
  9. #include <Tests/ComponentModeTestFixture.h>
  10. #include <AzCore/std/smart_ptr/make_shared.h>
  11. #include <AzCore/std/smart_ptr/shared_ptr.h>
  12. #include <AzFramework/Viewport/ViewportScreen.h>
  13. #include <AzTest/AzTest.h>
  14. #include <AzToolsFramework/API/EntityCompositionRequestBus.h>
  15. #include <AzToolsFramework/Application/ToolsApplication.h>
  16. #include <AzToolsFramework/ComponentMode/ComponentModeSwitcher.h>
  17. #include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
  18. #include <AzToolsFramework/ViewportUi/ButtonGroup.h>
  19. #include <AzToolsFramework/ViewportUi/ViewportUiManager.h>
  20. #include <AzToolsFramework/ViewportUi/ViewportUiSwitcher.h>
  21. #include <AzToolsFramework/API/EntityCompositionRequestBus.h>
  22. namespace UnitTest
  23. {
  24. using AzToolsFramework::ComponentModeFramework::PlaceholderEditorComponent;
  25. using AzToolsFramework::ComponentModeFramework::AnotherPlaceholderEditorComponent;
  26. using AzToolsFramework::ComponentModeFramework::DependentPlaceholderEditorComponent;
  27. using ComponentModeSwitcher = AzToolsFramework::ComponentModeFramework::ComponentModeSwitcher;
  28. using ComponentModeSwitcherTestFixture = ComponentModeTestFixture;
  29. TEST_F(ComponentModeSwitcherTestFixture, AddingComponentsToEntityAddsComponentsToSwitcher)
  30. {
  31. // Given the setup of one entity with one component
  32. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  33. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  34. AzToolsFramework::GetEntityContextId(),
  35. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  36. componentModeSwitcher);
  37. AZ::Entity* entity = nullptr;
  38. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  39. entity->Deactivate();
  40. entity->CreateComponent<PlaceholderEditorComponent>();
  41. entity->Activate();
  42. // When the entity is selected, expect the switcher to have one component
  43. const AzToolsFramework::EntityIdList entityIds = { entityId };
  44. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  45. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  46. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  47. // Then when another component is added to the entity, expect the switcher to have two components
  48. AzToolsFramework::EntityCompositionRequests::AddComponentsOutcome addComponentsOutcome;
  49. AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(
  50. addComponentsOutcome,
  51. &AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities,
  52. entityIds,
  53. AZ::ComponentTypeList{ AnotherPlaceholderEditorComponent::RTTI_Type() });
  54. EXPECT_EQ(2, componentModeSwitcher->GetComponentCount());
  55. }
  56. TEST_F(ComponentModeSwitcherTestFixture, RemovingComponentsFromEntityRemovesComponentsFromSwitcher)
  57. {
  58. // Given the set up of one entity selected with two components
  59. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  60. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  61. AzToolsFramework::GetEntityContextId(),
  62. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  63. componentModeSwitcher);
  64. AZ::Entity* entity = nullptr;
  65. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  66. entity->Deactivate();
  67. entity->CreateComponent<PlaceholderEditorComponent>();
  68. AZ::Component* placeholder2 = entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  69. entity->Activate();
  70. // When the user selects the entity, two components show up in the switcher
  71. const AzToolsFramework::EntityIdList entityIds = { entityId };
  72. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  73. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  74. EXPECT_EQ(2, componentModeSwitcher->GetComponentCount());
  75. // Then when the user removes a component, one component remains
  76. AzToolsFramework::EntityCompositionRequests::RemoveComponentsOutcome removeComponentsOutcome;
  77. AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(
  78. removeComponentsOutcome,
  79. &AzToolsFramework::EntityCompositionRequests::RemoveComponents,
  80. AZ::Entity::ComponentArrayType{ placeholder2 });
  81. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  82. }
  83. TEST_F(ComponentModeSwitcherTestFixture, InstantaneousChangeOfEntitySelectionUpdatesSwitcherCorrectly)
  84. {
  85. // Given an entity with two components
  86. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  87. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  88. AzToolsFramework::GetEntityContextId(),
  89. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  90. componentModeSwitcher);
  91. AZ::Entity* entity = nullptr;
  92. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  93. AZ::Entity* entity2 = nullptr;
  94. AZ::EntityId entityId2 = CreateDefaultEditorEntity("ComponentModeEntity", &entity2);
  95. entity->Deactivate();
  96. entity2->Deactivate();
  97. entity->CreateComponent<PlaceholderEditorComponent>();
  98. entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  99. entity2->CreateComponent<AnotherPlaceholderEditorComponent>();
  100. entity->Activate();
  101. entity2->Activate();
  102. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  103. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, AzToolsFramework::EntityIdList{ entityId });
  104. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  105. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, AzToolsFramework::EntityIdList{ entityId2 });
  106. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  107. }
  108. TEST_F(ComponentModeSwitcherTestFixture, AddingDuplicateComponentsDoesNotAddComponentsToSwitcher)
  109. {
  110. // Given an entity with one component
  111. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  112. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  113. AzToolsFramework::GetEntityContextId(),
  114. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  115. componentModeSwitcher);
  116. AZ::Entity* entity = nullptr;
  117. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  118. entity->Deactivate();
  119. entity->CreateComponent<PlaceholderEditorComponent>();
  120. entity->Activate();
  121. // When an entity is selected, there is one component added to the switcher
  122. const AzToolsFramework::EntityIdList entityIds = { entityId };
  123. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  124. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  125. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  126. // Then if the user adds an identical component, there is still one component on the switcher
  127. entity->Deactivate();
  128. entity->CreateComponent<PlaceholderEditorComponent>();
  129. entity->Activate();
  130. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  131. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  132. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  133. }
  134. TEST_F(ComponentModeSwitcherTestFixture, SelectingAndDeselectingEntitiesAddsAndRemovesComponentsFromSwitcher)
  135. {
  136. // Given an entity with multiple components
  137. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  138. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  139. AzToolsFramework::GetEntityContextId(),
  140. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  141. componentModeSwitcher);
  142. AZ::Entity* entity = nullptr;
  143. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  144. entity->Deactivate();
  145. entity->CreateComponent<PlaceholderEditorComponent>();
  146. entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  147. entity->Activate();
  148. // When the entity is selected, there are two components on the switcher
  149. const AzToolsFramework::EntityIdList entityIds = { entityId };
  150. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  151. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  152. EXPECT_EQ(2, componentModeSwitcher->GetComponentCount());
  153. // Then when the entity is deselected
  154. const AzToolsFramework::EntityIdList emptyIds = {};
  155. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, emptyIds);
  156. EXPECT_EQ(0, componentModeSwitcher->GetComponentCount());
  157. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  158. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  159. EXPECT_EQ(2, componentModeSwitcher->GetComponentCount());
  160. }
  161. TEST_F(ComponentModeSwitcherTestFixture, AddIngMultipleEntitiesToSelectionWithSameComponentsKeepComponentsInSwitcher)
  162. {
  163. // Given two entities with different components
  164. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  165. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  166. AzToolsFramework::GetEntityContextId(),
  167. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  168. componentModeSwitcher);
  169. AZ::Entity* entity = nullptr;
  170. AZ::Entity* entity2 = nullptr;
  171. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  172. AZ::EntityId entityId2 = CreateDefaultEditorEntity("ComponentModeEntity2", &entity2);
  173. entity->Deactivate();
  174. entity2->Deactivate();
  175. entity->CreateComponent<PlaceholderEditorComponent>();
  176. entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  177. entity2->CreateComponent<PlaceholderEditorComponent>();
  178. entity->Activate();
  179. entity2->Activate();
  180. // When one entity is selected all associated components show up in the switcher
  181. AzToolsFramework::EntityIdList entityIds = { entityId };
  182. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  183. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  184. EXPECT_EQ(2, componentModeSwitcher->GetComponentCount());
  185. // Then if both entities are selected, only components that are shared between both entities show up
  186. entityIds = { entityId, entityId2 };
  187. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  188. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  189. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  190. }
  191. TEST_F(ComponentModeSwitcherTestFixture, AddingMultipleEntityToSelectionWithUniqueComponentsRemovesUniqueFromSwitcher)
  192. {
  193. // Given two entities with multiple components
  194. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  195. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  196. AzToolsFramework::GetEntityContextId(),
  197. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  198. componentModeSwitcher);
  199. AZ::Entity* entity = nullptr;
  200. AZ::Entity* entity2 = nullptr;
  201. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  202. AZ::EntityId entityId2 = CreateDefaultEditorEntity("ComponentModeEntity2", &entity2);
  203. entity->Deactivate();
  204. entity2->Deactivate();
  205. entity->CreateComponent<PlaceholderEditorComponent>();
  206. entity2->CreateComponent<AnotherPlaceholderEditorComponent>();
  207. entity->Activate();
  208. entity2->Activate();
  209. // When one entity is selected the component shows up like normal
  210. AzToolsFramework::EntityIdList entityIds = { entityId };
  211. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  212. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  213. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  214. // When both entities are selected, if there are no common components, the switcher is empty
  215. entityIds = { entityId, entityId2 };
  216. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  217. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  218. EXPECT_EQ(0, componentModeSwitcher->GetComponentCount());
  219. }
  220. TEST_F(ComponentModeSwitcherTestFixture, DeselectingOneEntityWithMultipleEntitiesSelectedAddsRemovedComponents)
  221. {
  222. // Given two entities with different components
  223. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  224. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  225. AzToolsFramework::GetEntityContextId(),
  226. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  227. componentModeSwitcher);
  228. AZ::Entity* entity = nullptr;
  229. AZ::Entity* entity2 = nullptr;
  230. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  231. AZ::EntityId entityId2 = CreateDefaultEditorEntity("ComponentModeEntity2", &entity2);
  232. entity->Deactivate();
  233. entity2->Deactivate();
  234. entity->CreateComponent<PlaceholderEditorComponent>();
  235. entity2->CreateComponent<AnotherPlaceholderEditorComponent>();
  236. entity->Activate();
  237. entity2->Activate();
  238. // When the both entities are selected, nothing shows up in the switcher as there are no common components
  239. AzToolsFramework::EntityIdList entityIds = { entityId };
  240. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  241. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  242. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  243. entityIds = { entityId, entityId2 };
  244. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  245. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  246. EXPECT_EQ(0, componentModeSwitcher->GetComponentCount());
  247. // When the second entity is removed from the selection, the switcher now has the component from the single entity selected
  248. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::DeleteEntityById, entityId2);
  249. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  250. }
  251. TEST_F(ComponentModeSwitcherTestFixture, EnteringComponentModeChangesActiveComponent)
  252. {
  253. // Given an entity with two components
  254. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  255. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  256. AzToolsFramework::GetEntityContextId(),
  257. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  258. componentModeSwitcher);
  259. AZ::Entity* entity = nullptr;
  260. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  261. entity->Deactivate();
  262. const AZ::Component* placeholder1 = entity->CreateComponent<PlaceholderEditorComponent>();
  263. entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  264. entity->Activate();
  265. // When component mode is activated for a component in any way (through the switcher or the entity tab)
  266. const AzToolsFramework::EntityIdList entityIds = { entityId };
  267. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  268. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  269. AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
  270. &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::AddSelectedComponentModesOfType,
  271. placeholder1->GetUnderlyingComponentType());
  272. // Then the switchers active button is the component that component mode is active for
  273. auto activeComponent = componentModeSwitcher->GetActiveComponent()->GetId();
  274. EXPECT_EQ(activeComponent, placeholder1->GetId());
  275. }
  276. TEST_F(ComponentModeSwitcherTestFixture, LeavingComponentModeChangesActiveComponentToTransformMode)
  277. {
  278. // Given an entity with two components
  279. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  280. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  281. AzToolsFramework::GetEntityContextId(),
  282. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  283. componentModeSwitcher);
  284. AZ::Entity* entity = nullptr;
  285. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  286. entity->Deactivate();
  287. entity->CreateComponent<PlaceholderEditorComponent>();
  288. const AZ::Component* placeholder2 = entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  289. entity->Activate();
  290. const AzToolsFramework::EntityIdList entityIds = { entityId };
  291. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  292. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  293. // When component mode is de-activated for a component in any way (through the switcher or the entity tab)
  294. AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
  295. &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::AddSelectedComponentModesOfType,
  296. placeholder2->GetUnderlyingComponentType());
  297. auto activeComponent = componentModeSwitcher->GetActiveComponent()->GetId();
  298. EXPECT_EQ(activeComponent, placeholder2->GetId());
  299. AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
  300. &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::EndComponentMode);
  301. // Then the active switcher button should be the transform component (indicated by null)
  302. auto nullComponent = componentModeSwitcher->GetActiveComponent();
  303. EXPECT_EQ(nullComponent, nullptr);
  304. }
  305. TEST_F(ComponentModeSwitcherTestFixture, DisablingComponentRemovesComponentFromSwitcher)
  306. {
  307. // Given an entity with two components
  308. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  309. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  310. AzToolsFramework::GetEntityContextId(),
  311. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  312. componentModeSwitcher);
  313. AZ::Entity* entity = nullptr;
  314. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  315. entity->Deactivate();
  316. AZStd::unique_ptr<AZ::Component> placeholder1{entity->CreateComponent<PlaceholderEditorComponent>()};
  317. entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  318. entity->Activate();
  319. // When the entity is selected there should be two components in the switcher
  320. const AzToolsFramework::EntityIdList entityIds = { entityId };
  321. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  322. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  323. EXPECT_EQ(2, componentModeSwitcher->GetComponentCount());
  324. // Then if one component is disabled, there should only be one component on the switcher
  325. // Disabling the component removes it from the entity, which is why its ownership is maintained here in a
  326. // unique_ptr
  327. AzToolsFramework::EntityCompositionRequestBus::Broadcast(
  328. &AzToolsFramework::EntityCompositionRequests::DisableComponents, AZStd::vector<AZ::Component*>{ placeholder1.get() });
  329. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  330. entity->Deactivate();
  331. }
  332. TEST_F(ComponentModeSwitcherTestFixture, EnablingComponentAddsComponentToSwitcher)
  333. {
  334. // Given an entity with two components
  335. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  336. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  337. AzToolsFramework::GetEntityContextId(),
  338. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  339. componentModeSwitcher);
  340. AZ::Entity* entity = nullptr;
  341. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  342. // connect to EditorDisabledCompositionRequestBus with entityId
  343. Connect(entityId);
  344. entity->Deactivate();
  345. AZ::Component* placeholder1 = entity->CreateComponent<PlaceholderEditorComponent>();
  346. entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  347. entity->Activate();
  348. // When the component is disabled it doesn't show up in the switcher
  349. const AzToolsFramework::EntityIdList entityIds = { entityId };
  350. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  351. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  352. EXPECT_EQ(2, componentModeSwitcher->GetComponentCount());
  353. AzToolsFramework::EntityCompositionRequestBus::Broadcast(
  354. &AzToolsFramework::EntityCompositionRequests::DisableComponents, AZStd::vector<AZ::Component*>{ placeholder1 });
  355. AzToolsFramework::EditorDisabledCompositionRequestBus::Event(
  356. entityId, &AzToolsFramework::EditorDisabledCompositionRequests::AddDisabledComponent, placeholder1);
  357. EXPECT_EQ(1, componentModeSwitcher->GetComponentCount());
  358. AddDisabledComponentToBus(placeholder1);
  359. AzToolsFramework::EntityCompositionRequestBus::Broadcast(
  360. &AzToolsFramework::EntityCompositionRequests::EnableComponents, AZStd::vector<AZ::Component*>{ placeholder1 });
  361. EXPECT_EQ(2, componentModeSwitcher->GetComponentCount());
  362. Disconnect();
  363. }
  364. TEST_F(ComponentModeSwitcherTestFixture, SwitchingBetweenComponentsDoesNotSwitchToTransformFirst)
  365. {
  366. // Given an entity with two components
  367. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  368. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  369. AzToolsFramework::GetEntityContextId(),
  370. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  371. componentModeSwitcher);
  372. AZ::Entity* entity = nullptr;
  373. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  374. entity->Deactivate();
  375. const AZ::Component* placeholder = entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  376. const AZ::Component* dependentPlaceholder = entity->CreateComponent<DependentPlaceholderEditorComponent>();
  377. entity->Activate();
  378. const AzToolsFramework::EntityIdList entityIds = { entityId };
  379. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  380. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  381. AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
  382. &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::AddSelectedComponentModesOfType,
  383. dependentPlaceholder->GetUnderlyingComponentType());
  384. auto activeComponent = componentModeSwitcher->GetActiveComponent()->GetId();
  385. EXPECT_EQ(activeComponent, dependentPlaceholder->GetId());
  386. // When the user is in a dependent component mode and presses tab
  387. QTest::keyPress(&m_editorActions.m_componentModeWidget, Qt::Key_Tab);
  388. // The swticher changes to the next active component mode
  389. activeComponent = componentModeSwitcher->GetActiveComponent()->GetId();
  390. EXPECT_EQ(activeComponent, placeholder->GetId());
  391. }
  392. TEST_F(ComponentModeSwitcherTestFixture, SwitcherDoesNotChangeCompositionWhileInComponentMode)
  393. {
  394. // Given an entity with two components
  395. AZStd::shared_ptr<ComponentModeSwitcher> componentModeSwitcher = AZStd::make_shared<ComponentModeSwitcher>();
  396. AzToolsFramework::EditorTransformComponentSelectionRequestBus::Event(
  397. AzToolsFramework::GetEntityContextId(),
  398. &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::OverrideComponentModeSwitcher,
  399. componentModeSwitcher);
  400. AZ::Entity* entity = nullptr;
  401. AZ::EntityId entityId = CreateDefaultEditorEntity("ComponentModeEntity", &entity);
  402. entity->Deactivate();
  403. const AZ::Component* placeholder = entity->CreateComponent<AnotherPlaceholderEditorComponent>();
  404. const AZ::Component* dependentPlaceholder = entity->CreateComponent<DependentPlaceholderEditorComponent>();
  405. entity->Activate();
  406. const AzToolsFramework::EntityIdList entityIds = { entityId };
  407. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  408. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entityIds);
  409. // When the editor enters component mode
  410. AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
  411. &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::AddSelectedComponentModesOfType,
  412. dependentPlaceholder->GetUnderlyingComponentType());
  413. EXPECT_TRUE(AzToolsFramework::ComponentModeFramework::InComponentMode());
  414. EXPECT_EQ(componentModeSwitcher->GetComponentCount(), 2);
  415. // While in component mode
  416. AzFramework::ComponentModeDelegateNotificationBus::Broadcast(
  417. &AzFramework::ComponentModeDelegateNotificationBus::Events::OnComponentModeDelegateDisconnect, AZ::EntityComponentIdPair(entityId, placeholder->GetId()));
  418. EXPECT_EQ(componentModeSwitcher->GetComponentCount(), 2);
  419. }
  420. } // namespace UnitTest