UiLayoutManager.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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 "UiLayoutManager.h"
  9. #include <LyShine/Bus/UiLayoutBus.h>
  10. #include <LyShine/Bus/UiElementBus.h>
  11. #include <LyShine/Bus/UiLayoutControllerBus.h>
  12. ////////////////////////////////////////////////////////////////////////////////////////////////////
  13. // PUBLIC MEMBER FUNCTIONS
  14. ////////////////////////////////////////////////////////////////////////////////////////////////////
  15. ////////////////////////////////////////////////////////////////////////////////////////////////////
  16. UiLayoutManager::UiLayoutManager(AZ::EntityId canvasEntityId)
  17. {
  18. UiLayoutManagerBus::Handler::BusConnect(canvasEntityId);
  19. }
  20. ////////////////////////////////////////////////////////////////////////////////////////////////////
  21. UiLayoutManager::~UiLayoutManager()
  22. {
  23. UiLayoutManagerBus::Handler::BusDisconnect();
  24. }
  25. ////////////////////////////////////////////////////////////////////////////////////////////////////
  26. void UiLayoutManager::MarkToRecomputeLayout(AZ::EntityId entityId)
  27. {
  28. if (UiLayoutControllerBus::FindFirstHandler(entityId))
  29. {
  30. AddToRecomputeLayoutList(entityId);
  31. }
  32. }
  33. ////////////////////////////////////////////////////////////////////////////////////////////////////
  34. void UiLayoutManager::MarkToRecomputeLayoutsAffectedByLayoutCellChange(AZ::EntityId entityId, bool isDefaultLayoutCell)
  35. {
  36. AZ::EntityId topParent;
  37. AZ::EntityId parent;
  38. UiElementBus::EventResult(parent, entityId, &UiElementBus::Events::GetParentEntityId);
  39. while (parent.IsValid())
  40. {
  41. bool usesLayoutCells = false;
  42. UiLayoutBus::EventResult(usesLayoutCells, parent, &UiLayoutBus::Events::IsUsingLayoutCellsToCalculateLayout);
  43. if (usesLayoutCells && isDefaultLayoutCell)
  44. {
  45. bool ignoreDefaultLayoutCells = true;
  46. UiLayoutBus::EventResult(ignoreDefaultLayoutCells, parent, &UiLayoutBus::Events::GetIgnoreDefaultLayoutCells);
  47. usesLayoutCells = !ignoreDefaultLayoutCells;
  48. }
  49. if (usesLayoutCells)
  50. {
  51. topParent = parent;
  52. parent.SetInvalid();
  53. UiElementBus::EventResult(parent, topParent, &UiElementBus::Events::GetParentEntityId);
  54. }
  55. else
  56. {
  57. break;
  58. }
  59. }
  60. if (topParent.IsValid())
  61. {
  62. AddToRecomputeLayoutList(topParent);
  63. }
  64. }
  65. ////////////////////////////////////////////////////////////////////////////////////////////////////
  66. void UiLayoutManager::UnmarkAllLayouts()
  67. {
  68. m_elementsToRecomputeLayout.clear();
  69. }
  70. ////////////////////////////////////////////////////////////////////////////////////////////////////
  71. void UiLayoutManager::RecomputeMarkedLayouts()
  72. {
  73. for (auto element : m_elementsToRecomputeLayout)
  74. {
  75. ComputeLayoutForElementAndDescendants(element);
  76. }
  77. UnmarkAllLayouts();
  78. }
  79. ////////////////////////////////////////////////////////////////////////////////////////////////////
  80. void UiLayoutManager::ComputeLayoutForElementAndDescendants(AZ::EntityId entityId)
  81. {
  82. // Get a list of layout children
  83. auto FindLayoutChildren = [](const AZ::Entity* entity)
  84. {
  85. return (UiLayoutControllerBus::FindFirstHandler(entity->GetId())) ? true : false;
  86. };
  87. LyShine::EntityArray layoutChildren;
  88. UiElementBus::Event(entityId, &UiElementBus::Events::FindDescendantElements, FindLayoutChildren, layoutChildren);
  89. UiLayoutControllerBus::Event(entityId, &UiLayoutControllerBus::Events::ApplyLayoutWidth);
  90. for (auto layoutChild : layoutChildren)
  91. {
  92. UiLayoutControllerBus::Event(layoutChild->GetId(), &UiLayoutControllerBus::Events::ApplyLayoutWidth);
  93. }
  94. UiLayoutControllerBus::Event(entityId, &UiLayoutControllerBus::Events::ApplyLayoutHeight);
  95. for (auto layoutChild : layoutChildren)
  96. {
  97. UiLayoutControllerBus::Event(layoutChild->GetId(), &UiLayoutControllerBus::Events::ApplyLayoutHeight);
  98. }
  99. }
  100. ////////////////////////////////////////////////////////////////////////////////////////////////////
  101. // PRIVATE MEMBER FUNCTIONS
  102. ////////////////////////////////////////////////////////////////////////////////////////////////////
  103. ////////////////////////////////////////////////////////////////////////////////////////////////////
  104. void UiLayoutManager::AddToRecomputeLayoutList(AZ::EntityId entityId)
  105. {
  106. // Check if element is already in the list
  107. auto iter = AZStd::find(m_elementsToRecomputeLayout.begin(), m_elementsToRecomputeLayout.end(), entityId);
  108. if (iter == m_elementsToRecomputeLayout.end())
  109. {
  110. // Check if element's parent is already in the list
  111. for (iter = m_elementsToRecomputeLayout.begin(); iter != m_elementsToRecomputeLayout.end(); ++iter)
  112. {
  113. if (IsParentOfElement(*iter, entityId))
  114. {
  115. // Don't need to add this element
  116. return;
  117. }
  118. }
  119. // Remove element's children from the list
  120. LyShine::EntityArray descendants;
  121. UiElementBus::Event(
  122. entityId,
  123. &UiElementBus::Events::FindDescendantElements,
  124. []([[maybe_unused]] const AZ::Entity* entity)
  125. {
  126. return true;
  127. },
  128. descendants);
  129. m_elementsToRecomputeLayout.remove_if(
  130. [descendants](const AZ::EntityId& e)
  131. {
  132. for (auto descendant : descendants)
  133. {
  134. if (descendant->GetId() == e)
  135. {
  136. return true;
  137. }
  138. }
  139. return false;
  140. }
  141. );
  142. // Add element to list
  143. m_elementsToRecomputeLayout.push_back(entityId);
  144. }
  145. }
  146. ////////////////////////////////////////////////////////////////////////////////////////////////////
  147. bool UiLayoutManager::IsParentOfElement(AZ::EntityId checkParentEntity, AZ::EntityId checkChildEntity)
  148. {
  149. AZ::EntityId parent;
  150. UiElementBus::EventResult(parent, checkChildEntity, &UiElementBus::Events::GetParentEntityId);
  151. while (parent.IsValid())
  152. {
  153. if (parent == checkParentEntity)
  154. {
  155. return true;
  156. }
  157. AZ::EntityId newParent = parent;
  158. parent.SetInvalid();
  159. UiElementBus::EventResult(parent, newParent, &UiElementBus::Events::GetParentEntityId);
  160. }
  161. return false;
  162. }