3
0

UiLayoutRowComponent.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  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 "UiLayoutRowComponent.h"
  9. #include <AzCore/Serialization/SerializeContext.h>
  10. #include <AzCore/Serialization/EditContext.h>
  11. #include <AzCore/RTTI/BehaviorContext.h>
  12. #include <LyShine/Bus/UiElementBus.h>
  13. #include <LyShine/Bus/UiTransform2dBus.h>
  14. #include <LyShine/Bus/UiLayoutManagerBus.h>
  15. #include "UiSerialize.h"
  16. ////////////////////////////////////////////////////////////////////////////////////////////////////
  17. // PUBLIC MEMBER FUNCTIONS
  18. ////////////////////////////////////////////////////////////////////////////////////////////////////
  19. ////////////////////////////////////////////////////////////////////////////////////////////////////
  20. UiLayoutRowComponent::UiLayoutRowComponent()
  21. : m_padding(UiLayoutInterface::Padding())
  22. , m_spacing(5)
  23. , m_order(UiLayoutInterface::HorizontalOrder::LeftToRight)
  24. , m_childHAlignment(IDraw2d::HAlign::Left)
  25. , m_childVAlignment(IDraw2d::VAlign::Top)
  26. , m_ignoreDefaultLayoutCells(true)
  27. {
  28. }
  29. ////////////////////////////////////////////////////////////////////////////////////////////////////
  30. UiLayoutRowComponent::~UiLayoutRowComponent()
  31. {
  32. }
  33. ////////////////////////////////////////////////////////////////////////////////////////////////////
  34. void UiLayoutRowComponent::ApplyLayoutWidth()
  35. {
  36. // Get the layout rect inside the padding
  37. AZ::Vector2 layoutRectSize(0.0f, 0.0f);
  38. UiLayoutHelpers::GetSizeInsidePadding(GetEntityId(), m_padding, layoutRectSize);
  39. // First, calculate and set the child elements' widths.
  40. // Min/target/extra heights may depend on element widths
  41. ApplyLayoutWidth(layoutRectSize.GetX());
  42. }
  43. ////////////////////////////////////////////////////////////////////////////////////////////////////
  44. void UiLayoutRowComponent::ApplyLayoutHeight()
  45. {
  46. // Get the layout rect inside the padding
  47. AZ::Vector2 layoutRectSize(0.0f, 0.0f);
  48. UiLayoutHelpers::GetSizeInsidePadding(GetEntityId(), m_padding, layoutRectSize);
  49. // Calculate and set the child elements' heights
  50. ApplyLayoutHeight(layoutRectSize.GetY());
  51. }
  52. ////////////////////////////////////////////////////////////////////////////////////////////////////
  53. bool UiLayoutRowComponent::IsUsingLayoutCellsToCalculateLayout()
  54. {
  55. return true;
  56. }
  57. ////////////////////////////////////////////////////////////////////////////////////////////////////
  58. bool UiLayoutRowComponent::GetIgnoreDefaultLayoutCells()
  59. {
  60. return m_ignoreDefaultLayoutCells;
  61. }
  62. ////////////////////////////////////////////////////////////////////////////////////////////////////
  63. void UiLayoutRowComponent::SetIgnoreDefaultLayoutCells(bool ignoreDefaultLayoutCells)
  64. {
  65. m_ignoreDefaultLayoutCells = ignoreDefaultLayoutCells;
  66. InvalidateLayout();
  67. InvalidateParentLayout();
  68. }
  69. ////////////////////////////////////////////////////////////////////////////////////////////////////
  70. IDraw2d::HAlign UiLayoutRowComponent::GetHorizontalChildAlignment()
  71. {
  72. return m_childHAlignment;
  73. }
  74. ////////////////////////////////////////////////////////////////////////////////////////////////////
  75. void UiLayoutRowComponent::SetHorizontalChildAlignment(IDraw2d::HAlign alignment)
  76. {
  77. m_childHAlignment = alignment;
  78. InvalidateLayout();
  79. }
  80. ////////////////////////////////////////////////////////////////////////////////////////////////////
  81. IDraw2d::VAlign UiLayoutRowComponent::GetVerticalChildAlignment()
  82. {
  83. return m_childVAlignment;
  84. }
  85. ////////////////////////////////////////////////////////////////////////////////////////////////////
  86. void UiLayoutRowComponent::SetVerticalChildAlignment(IDraw2d::VAlign alignment)
  87. {
  88. m_childVAlignment = alignment;
  89. InvalidateLayout();
  90. }
  91. ////////////////////////////////////////////////////////////////////////////////////////////////////
  92. bool UiLayoutRowComponent::IsControllingChild(AZ::EntityId childId)
  93. {
  94. return UiLayoutHelpers::IsControllingChild(GetEntityId(), childId);
  95. }
  96. ////////////////////////////////////////////////////////////////////////////////////////////////////
  97. AZ::Vector2 UiLayoutRowComponent::GetSizeToFitChildElements(const AZ::Vector2& childElementSize, int numChildElements)
  98. {
  99. AZ::Vector2 size(0.0f, 0.0f);
  100. if (numChildElements > 0)
  101. {
  102. size.SetX((childElementSize.GetX() * numChildElements) + (m_spacing * (numChildElements - 1)) + m_padding.m_left + m_padding.m_right);
  103. }
  104. else
  105. {
  106. size.SetX(0.0f);
  107. }
  108. // Check if anchors are together
  109. UiTransform2dInterface::Anchors anchors;
  110. UiTransform2dBus::EventResult(anchors, GetEntityId(), &UiTransform2dBus::Events::GetAnchors);
  111. if (anchors.m_top == anchors.m_bottom)
  112. {
  113. size.SetY(numChildElements > 0 ? childElementSize.GetY() : 0.0f);
  114. }
  115. else
  116. {
  117. // Anchors are apart, so height remains untouched
  118. AZ::Vector2 curSize(0.0f, 0.0f);
  119. UiTransformBus::EventResult(curSize, GetEntityId(), &UiTransformBus::Events::GetCanvasSpaceSizeNoScaleRotate);
  120. size.SetY(curSize.GetY());
  121. }
  122. return size;
  123. }
  124. ////////////////////////////////////////////////////////////////////////////////////////////////////
  125. UiLayoutInterface::Padding UiLayoutRowComponent::GetPadding()
  126. {
  127. return m_padding;
  128. }
  129. ////////////////////////////////////////////////////////////////////////////////////////////////////
  130. void UiLayoutRowComponent::SetPadding(UiLayoutInterface::Padding padding)
  131. {
  132. m_padding = padding;
  133. InvalidateLayout();
  134. InvalidateParentLayout();
  135. }
  136. ////////////////////////////////////////////////////////////////////////////////////////////////////
  137. float UiLayoutRowComponent::GetSpacing()
  138. {
  139. return m_spacing;
  140. }
  141. ////////////////////////////////////////////////////////////////////////////////////////////////////
  142. void UiLayoutRowComponent::SetSpacing(float spacing)
  143. {
  144. m_spacing = spacing;
  145. InvalidateLayout();
  146. InvalidateParentLayout();
  147. }
  148. ////////////////////////////////////////////////////////////////////////////////////////////////////
  149. UiLayoutInterface::HorizontalOrder UiLayoutRowComponent::GetOrder()
  150. {
  151. return m_order;
  152. }
  153. ////////////////////////////////////////////////////////////////////////////////////////////////////
  154. void UiLayoutRowComponent::SetOrder(UiLayoutInterface::HorizontalOrder order)
  155. {
  156. m_order = order;
  157. InvalidateLayout();
  158. }
  159. ////////////////////////////////////////////////////////////////////////////////////////////////////
  160. float UiLayoutRowComponent::GetMinWidth()
  161. {
  162. float width = 0.0f;
  163. // Minimum layout width is padding + spacing + sum of all child element min widths
  164. AZStd::vector<float> minWidths = UiLayoutHelpers::GetLayoutCellMinWidths(GetEntityId(), m_ignoreDefaultLayoutCells);
  165. if (minWidths.size() > 0)
  166. {
  167. width += m_padding.m_left + m_padding.m_right + (m_spacing * (minWidths.size() - 1));
  168. for (auto minWidth : minWidths)
  169. {
  170. width += minWidth;
  171. }
  172. }
  173. return width;
  174. }
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////
  176. float UiLayoutRowComponent::GetMinHeight()
  177. {
  178. float height = 0.0f;
  179. // Minimum layout height is padding + maximum child element min height
  180. AZStd::vector<float> minHeights = UiLayoutHelpers::GetLayoutCellMinHeights(GetEntityId(), m_ignoreDefaultLayoutCells);
  181. if (minHeights.size() > 0)
  182. {
  183. height += m_padding.m_top + m_padding.m_bottom;
  184. float maxChildHeight = 0.0f;
  185. for (auto minHeight : minHeights)
  186. {
  187. if (maxChildHeight < minHeight)
  188. {
  189. maxChildHeight = minHeight;
  190. }
  191. }
  192. height += maxChildHeight;
  193. }
  194. return height;
  195. }
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////
  197. float UiLayoutRowComponent::GetTargetWidth(float /*maxWidth*/)
  198. {
  199. float width = 0.0f;
  200. // Target layout width is padding + spacing + sum of all child element target widths
  201. AZStd::vector<float> targetWidths = UiLayoutHelpers::GetLayoutCellTargetWidths(GetEntityId(), m_ignoreDefaultLayoutCells);
  202. if (targetWidths.size() > 0)
  203. {
  204. width += m_padding.m_left + m_padding.m_right + (m_spacing * (targetWidths.size() - 1));
  205. for (auto targetWidth : targetWidths)
  206. {
  207. width += targetWidth;
  208. }
  209. }
  210. return width;
  211. }
  212. ////////////////////////////////////////////////////////////////////////////////////////////////////
  213. float UiLayoutRowComponent::GetTargetHeight(float /*maxHeight*/)
  214. {
  215. float height = 0.0f;
  216. // Target layout height is padding + maximum child element target height
  217. AZStd::vector<float> targetHeights = UiLayoutHelpers::GetLayoutCellTargetHeights(GetEntityId(), m_ignoreDefaultLayoutCells);
  218. if (targetHeights.size() > 0)
  219. {
  220. height += m_padding.m_top + m_padding.m_bottom;
  221. float maxChildHeight = 0.0f;
  222. for (auto targetHeight : targetHeights)
  223. {
  224. if (maxChildHeight < targetHeight)
  225. {
  226. maxChildHeight = targetHeight;
  227. }
  228. }
  229. height += maxChildHeight;
  230. }
  231. return height;
  232. }
  233. ////////////////////////////////////////////////////////////////////////////////////////////////////
  234. float UiLayoutRowComponent::GetExtraWidthRatio()
  235. {
  236. return 1.0f;
  237. }
  238. ////////////////////////////////////////////////////////////////////////////////////////////////////
  239. float UiLayoutRowComponent::GetExtraHeightRatio()
  240. {
  241. return 1.0f;
  242. }
  243. ////////////////////////////////////////////////////////////////////////////////////////////////////
  244. void UiLayoutRowComponent::OnCanvasSpaceRectChanged([[maybe_unused]] AZ::EntityId entityId, const UiTransformInterface::Rect& oldRect, const UiTransformInterface::Rect& newRect)
  245. {
  246. // If old rect equals new rect, size changed due to initialization
  247. bool sizeChanged = (oldRect == newRect) || (!oldRect.GetSize().IsClose(newRect.GetSize(), 0.05f));
  248. if (sizeChanged)
  249. {
  250. InvalidateLayout();
  251. }
  252. }
  253. ////////////////////////////////////////////////////////////////////////////////////////////////////
  254. // PUBLIC STATIC MEMBER FUNCTIONS
  255. ////////////////////////////////////////////////////////////////////////////////////////////////////
  256. void UiLayoutRowComponent::Reflect(AZ::ReflectContext* context)
  257. {
  258. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  259. if (serializeContext)
  260. {
  261. serializeContext->Class<UiLayoutRowComponent, AZ::Component>()
  262. ->Version(2, &VersionConverter)
  263. ->Field("Padding", &UiLayoutRowComponent::m_padding)
  264. ->Field("Spacing", &UiLayoutRowComponent::m_spacing)
  265. ->Field("Order", &UiLayoutRowComponent::m_order)
  266. ->Field("ChildHAlignment", &UiLayoutRowComponent::m_childHAlignment)
  267. ->Field("ChildVAlignment", &UiLayoutRowComponent::m_childVAlignment)
  268. ->Field("IgnoreDefaultLayoutCells", &UiLayoutRowComponent::m_ignoreDefaultLayoutCells);
  269. AZ::EditContext* ec = serializeContext->GetEditContext();
  270. if (ec)
  271. {
  272. auto editInfo = ec->Class<UiLayoutRowComponent>("LayoutRow", "A layout component that arranges its children in a row");
  273. editInfo->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  274. ->Attribute(AZ::Edit::Attributes::Category, "UI")
  275. ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/UiLayoutRow.png")
  276. ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/UiLayoutRow.png")
  277. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("UI", 0x27ff46b0))
  278. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  279. editInfo->DataElement(AZ::Edit::UIHandlers::LayoutPadding, &UiLayoutRowComponent::m_padding, "Padding", "The layout padding")
  280. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) // needed because sub-elements are hidden
  281. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::InvalidateLayout)
  282. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::InvalidateParentLayout)
  283. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::CheckLayoutFitterAndRefreshEditorTransformProperties);
  284. editInfo->DataElement(AZ::Edit::UIHandlers::SpinBox, &UiLayoutRowComponent::m_spacing, "Spacing", "The spacing between children")
  285. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  286. ->Attribute(AZ::Edit::Attributes::Step, 1.0f)
  287. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::InvalidateLayout)
  288. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::InvalidateParentLayout)
  289. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::CheckLayoutFitterAndRefreshEditorTransformProperties);
  290. editInfo->DataElement(AZ::Edit::UIHandlers::ComboBox, &UiLayoutRowComponent::m_order, "Order", "Which direction the row fills")
  291. ->EnumAttribute(UiLayoutInterface::HorizontalOrder::LeftToRight, "Left to right")
  292. ->EnumAttribute(UiLayoutInterface::HorizontalOrder::RightToLeft, "Right to left")
  293. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::InvalidateLayout);
  294. editInfo->DataElement(AZ::Edit::UIHandlers::CheckBox, &UiLayoutRowComponent::m_ignoreDefaultLayoutCells, "Ignore Default Cells",
  295. "When checked, fixed default layout cell values are used for child elements with no LayoutCell\n"
  296. "component rather than using defaults calculated by other components on the child.")
  297. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::InvalidateLayout)
  298. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::InvalidateParentLayout)
  299. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::CheckLayoutFitterAndRefreshEditorTransformProperties);
  300. // Alignment
  301. {
  302. editInfo->ClassElement(AZ::Edit::ClassElements::Group, "Child Alignment")
  303. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  304. editInfo->DataElement(AZ::Edit::UIHandlers::ComboBox, &UiLayoutRowComponent::m_childHAlignment, "Horizontal",
  305. "How to align the children if they don't take up all the available width")
  306. ->EnumAttribute(IDraw2d::HAlign::Left, "Left")
  307. ->EnumAttribute(IDraw2d::HAlign::Center, "Center")
  308. ->EnumAttribute(IDraw2d::HAlign::Right, "Right")
  309. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::InvalidateLayout);
  310. editInfo->DataElement(AZ::Edit::UIHandlers::ComboBox, &UiLayoutRowComponent::m_childVAlignment, "Vertical",
  311. "How to align the children if they don't take up all the available height")
  312. ->EnumAttribute(IDraw2d::VAlign::Top, "Top")
  313. ->EnumAttribute(IDraw2d::VAlign::Center, "Center")
  314. ->EnumAttribute(IDraw2d::VAlign::Bottom, "Bottom")
  315. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &UiLayoutRowComponent::InvalidateLayout);
  316. }
  317. }
  318. }
  319. AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
  320. if (behaviorContext)
  321. {
  322. behaviorContext->EBus<UiLayoutRowBus>("UiLayoutRowBus")
  323. ->Event("GetPadding", &UiLayoutRowBus::Events::GetPadding)
  324. ->Event("SetPadding", &UiLayoutRowBus::Events::SetPadding)
  325. ->Event("GetSpacing", &UiLayoutRowBus::Events::GetSpacing)
  326. ->Event("SetSpacing", &UiLayoutRowBus::Events::SetSpacing)
  327. ->Event("GetOrder", &UiLayoutRowBus::Events::GetOrder)
  328. ->Event("SetOrder", &UiLayoutRowBus::Events::SetOrder)
  329. ->VirtualProperty("Padding", "GetPadding", "SetPadding")
  330. ->VirtualProperty("Spacing", "GetSpacing", "SetSpacing");
  331. behaviorContext->Class<UiLayoutRowComponent>()->RequestBus("UiLayoutRowBus");
  332. }
  333. }
  334. ////////////////////////////////////////////////////////////////////////////////////////////////////
  335. // PROTECTED MEMBER FUNCTIONS
  336. ////////////////////////////////////////////////////////////////////////////////////////////////////
  337. ////////////////////////////////////////////////////////////////////////////////////////////////////
  338. void UiLayoutRowComponent::Activate()
  339. {
  340. UiLayoutBus::Handler::BusConnect(m_entity->GetId());
  341. UiLayoutControllerBus::Handler::BusConnect(m_entity->GetId());
  342. UiLayoutRowBus::Handler::BusConnect(m_entity->GetId());
  343. UiLayoutCellDefaultBus::Handler::BusConnect(m_entity->GetId());
  344. UiTransformChangeNotificationBus::Handler::BusConnect(m_entity->GetId());
  345. // If this is the first time the entity has been activated this has no effect since the canvas
  346. // is not known. But if a LayoutRow component has just been pasted onto an existing entity
  347. // we need to invalidate the layout in case that affects things.
  348. InvalidateLayout();
  349. InvalidateParentLayout();
  350. }
  351. ////////////////////////////////////////////////////////////////////////////////////////////////////
  352. void UiLayoutRowComponent::Deactivate()
  353. {
  354. UiLayoutBus::Handler::BusDisconnect();
  355. UiLayoutControllerBus::Handler::BusDisconnect();
  356. UiLayoutRowBus::Handler::BusDisconnect();
  357. UiLayoutCellDefaultBus::Handler::BusDisconnect();
  358. UiTransformChangeNotificationBus::Handler::BusDisconnect();
  359. // We could be about to remove this component and then reactivate the entity
  360. // which could affect the layout if there is a parent layout component
  361. InvalidateLayout();
  362. InvalidateParentLayout();
  363. }
  364. ////////////////////////////////////////////////////////////////////////////////////////////////////
  365. void UiLayoutRowComponent::InvalidateLayout()
  366. {
  367. UiLayoutHelpers::InvalidateLayout(GetEntityId());
  368. }
  369. ////////////////////////////////////////////////////////////////////////////////////////////////////
  370. void UiLayoutRowComponent::InvalidateParentLayout()
  371. {
  372. UiLayoutHelpers::InvalidateParentLayout(GetEntityId());
  373. }
  374. ////////////////////////////////////////////////////////////////////////////////////////////////////
  375. void UiLayoutRowComponent::CheckLayoutFitterAndRefreshEditorTransformProperties() const
  376. {
  377. UiLayoutHelpers::CheckFitterAndRefreshEditorTransformProperties(GetEntityId());
  378. }
  379. ////////////////////////////////////////////////////////////////////////////////////////////////////
  380. void UiLayoutRowComponent::ApplyLayoutWidth(float availableWidth)
  381. {
  382. // Get the child element cell widths
  383. UiLayoutHelpers::LayoutCellSizes layoutCells;
  384. UiLayoutHelpers::GetLayoutCellWidths(GetEntityId(), m_ignoreDefaultLayoutCells, layoutCells);
  385. int numChildren = static_cast<int>(layoutCells.size());
  386. if (numChildren > 0)
  387. {
  388. // Calculate child widths
  389. AZStd::vector<float> finalWidths(numChildren, 0.0f);
  390. UiLayoutHelpers::CalculateElementSizes(layoutCells, availableWidth, m_spacing, finalWidths);
  391. // Calculate occupied width
  392. float childrenRectWidth = (numChildren - 1) * m_spacing;
  393. for (auto width : finalWidths)
  394. {
  395. childrenRectWidth += width;
  396. }
  397. // Calculate alignment
  398. float alignmentOffset = UiLayoutHelpers::GetHorizontalAlignmentOffset(m_childHAlignment, availableWidth, childrenRectWidth);
  399. // Set the child elements' transform properties based on the calculated child widths
  400. UiTransform2dInterface::Anchors anchors(0.0f, 0.0f, 0.0f, 0.0f);
  401. AZStd::vector<AZ::EntityId> childEntityIds;
  402. UiElementBus::EventResult(childEntityIds, GetEntityId(), &UiElementBus::Events::GetChildEntityIds);
  403. float curX = alignmentOffset;
  404. switch (m_order)
  405. {
  406. case UiLayoutInterface::HorizontalOrder::LeftToRight:
  407. curX += m_padding.m_left;
  408. break;
  409. case UiLayoutInterface::HorizontalOrder::RightToLeft:
  410. curX += m_padding.m_left + childrenRectWidth;
  411. break;
  412. default:
  413. AZ_Assert(0, "Unrecognized HorizontalOrder type in UiLayoutRowComponent");
  414. break;
  415. }
  416. int childIndex = 0;
  417. for (auto child : childEntityIds)
  418. {
  419. // Set the anchors
  420. UiTransform2dBus::Event(child, &UiTransform2dBus::Events::SetAnchors, anchors, false, false);
  421. // Set the offsets
  422. UiTransform2dInterface::Offsets offsets;
  423. UiTransform2dBus::EventResult(offsets, child, &UiTransform2dBus::Events::GetOffsets);
  424. switch (m_order)
  425. {
  426. case UiLayoutInterface::HorizontalOrder::LeftToRight:
  427. offsets.m_left = curX;
  428. curX += finalWidths[childIndex];
  429. offsets.m_right = curX;
  430. curX += m_spacing;
  431. break;
  432. case UiLayoutInterface::HorizontalOrder::RightToLeft:
  433. offsets.m_right = curX;
  434. curX -= finalWidths[childIndex];
  435. offsets.m_left = curX;
  436. curX -= m_spacing;
  437. break;
  438. default:
  439. AZ_Assert(0, "Unrecognized HorizontalOrder type in UiLayoutRowComponent");
  440. break;
  441. }
  442. UiTransform2dBus::Event(child, &UiTransform2dBus::Events::SetOffsets, offsets);
  443. childIndex++;
  444. }
  445. }
  446. }
  447. ////////////////////////////////////////////////////////////////////////////////////////////////////
  448. void UiLayoutRowComponent::ApplyLayoutHeight(float availableHeight)
  449. {
  450. // Get the child element cell heights
  451. UiLayoutHelpers::LayoutCellSizes layoutCells;
  452. UiLayoutHelpers::GetLayoutCellHeights(GetEntityId(), m_ignoreDefaultLayoutCells, layoutCells);
  453. int numChildren = static_cast<int>(layoutCells.size());
  454. if (numChildren > 0)
  455. {
  456. // Set the child elements' transform properties based on the calculated child heights
  457. AZStd::vector<AZ::EntityId> childEntityIds;
  458. UiElementBus::EventResult(childEntityIds, GetEntityId(), &UiElementBus::Events::GetChildEntityIds);
  459. int childIndex = 0;
  460. for (auto child : childEntityIds)
  461. {
  462. // Calculate occupied height
  463. float height = UiLayoutHelpers::CalculateSingleElementSize(layoutCells[childIndex], availableHeight);
  464. // Calculate alignment
  465. float alignmentOffset = UiLayoutHelpers::GetVerticalAlignmentOffset(m_childVAlignment, availableHeight, height);
  466. // Set the offsets
  467. UiTransform2dInterface::Offsets offsets;
  468. UiTransform2dBus::EventResult(offsets, child, &UiTransform2dBus::Events::GetOffsets);
  469. offsets.m_top = m_padding.m_top + alignmentOffset;
  470. offsets.m_bottom = offsets.m_top + height;
  471. UiTransform2dBus::Event(child, &UiTransform2dBus::Events::SetOffsets, offsets);
  472. childIndex++;
  473. }
  474. }
  475. }
  476. ////////////////////////////////////////////////////////////////////////////////////////////////////
  477. // PRIVATE STATIC MEMBER FUNCTIONS
  478. ////////////////////////////////////////////////////////////////////////////////////////////////////
  479. ////////////////////////////////////////////////////////////////////////////////////////////////////
  480. bool UiLayoutRowComponent::VersionConverter(AZ::SerializeContext& context,
  481. AZ::SerializeContext::DataElementNode& classElement)
  482. {
  483. // conversion from version 1 to 2:
  484. // - Need to convert default m_ignoreDefaultLayoutCells to true
  485. if (classElement.GetVersion() < 2)
  486. {
  487. // Add a flag and set it to a value that's different from the default value for new components
  488. const char* subElementName = "IgnoreDefaultLayoutCells";
  489. int newElementIndex = classElement.AddElement<bool>(context, subElementName);
  490. if (newElementIndex == -1)
  491. {
  492. // Error adding the new sub element
  493. AZ_Error("Serialization", false, "AddElement failed for element %s", subElementName);
  494. return false;
  495. }
  496. classElement.GetSubElement(newElementIndex).SetData(context, true);
  497. }
  498. return true;
  499. }