BsGUILayoutUtility.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include "BsGUILayoutUtility.h"
  2. #include "BsGUIElementBase.h"
  3. #include "BsGUILayout.h"
  4. #include "BsGUIElement.h"
  5. #include "BsGUIElementStyle.h"
  6. #include "BsCGUIWidget.h"
  7. #include "BsViewport.h"
  8. #include "BsGUIPanel.h"
  9. #include "BsProfilerCPU.h"
  10. namespace BansheeEngine
  11. {
  12. Vector2I GUILayoutUtility::calcOptimalSize(const GUIElementBase* elem)
  13. {
  14. return elem->_calculateLayoutSizeRange().optimal;
  15. }
  16. Vector2I GUILayoutUtility::calcActualSize(UINT32 width, UINT32 height, GUILayout* layout, bool updateOptimalSizes)
  17. {
  18. if (updateOptimalSizes)
  19. layout->_updateOptimalLayoutSizes();
  20. return calcActualSizeInternal(width, height, layout);
  21. }
  22. Vector2I GUILayoutUtility::calcActualSizeInternal(UINT32 width, UINT32 height, GUILayout* layout)
  23. {
  24. UINT32 numElements = (UINT32)layout->_getNumChildren();
  25. Rect2I* elementAreas = nullptr;
  26. if (numElements > 0)
  27. elementAreas = bs_stack_new<Rect2I>(numElements);
  28. Rect2I parentArea;
  29. parentArea.width = width;
  30. parentArea.height = height;
  31. layout->_getElementAreas(parentArea, elementAreas, numElements, layout->_getCachedChildSizeRanges(), layout->_getCachedSizeRange());
  32. Rect2I* actualAreas = elementAreas; // We re-use the same array
  33. for (UINT32 i = 0; i < numElements; i++)
  34. {
  35. GUIElementBase* child = layout->_getChild(i);
  36. Rect2I childArea = elementAreas[i];
  37. if (child->_getType() == GUIElementBase::Type::Layout || child->_getType() == GUIElementBase::Type::Panel)
  38. {
  39. Vector2I childActualSize = calcActualSizeInternal(childArea.width, childArea.height, static_cast<GUILayout*>(child));
  40. actualAreas[i].width = (UINT32)childActualSize.x;
  41. actualAreas[i].height = (UINT32)childActualSize.y;
  42. }
  43. else if (child->_getType() == GUIElementBase::Type::Element)
  44. {
  45. RectOffset padding = child->_getPadding();
  46. actualAreas[i].width = elementAreas[i].width + padding.left + padding.right;
  47. actualAreas[i].height = elementAreas[i].height + padding.top + padding.bottom;
  48. }
  49. else
  50. {
  51. actualAreas[i].width = elementAreas[i].width;
  52. actualAreas[i].height = elementAreas[i].height;
  53. }
  54. }
  55. Vector2I min;
  56. Vector2I max;
  57. if (numElements > 0)
  58. {
  59. Rect2I childArea = actualAreas[0];
  60. min = Vector2I(childArea.x, childArea.y);
  61. max = Vector2I(childArea.x + childArea.width, childArea.y + childArea.height);
  62. }
  63. for (UINT32 i = 1; i < numElements; i++)
  64. {
  65. Rect2I childArea = actualAreas[i];
  66. min.x = std::min(min.x, childArea.x);
  67. min.y = std::min(min.y, childArea.y);
  68. max.x = std::max(max.x, childArea.x + childArea.width);
  69. max.y = std::max(max.y, childArea.y + childArea.height);
  70. }
  71. Vector2I actualSize = max - min;
  72. if (elementAreas != nullptr)
  73. bs_stack_free(elementAreas);
  74. return actualSize;
  75. }
  76. }