BsGUIArea.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "BsGUIArea.h"
  2. #include "BsGUIWidget.h"
  3. #include "BsGUILayoutX.h"
  4. #include "BsGUILayoutY.h"
  5. #include "BsGUILayoutExplicit.h"
  6. #include "BsGUIWidget.h"
  7. #include "BsRenderWindow.h"
  8. #include "BsViewport.h"
  9. namespace BansheeEngine
  10. {
  11. GUIArea::GUIArea(GUIWidget* widget, INT32 x, INT32 y, UINT16 depth, GUILayoutType layoutType)
  12. :mWidget(widget), mLeft(x), mTop(y), mDepth(depth), mIsDirty(true), mIsDisabled(false), mLayout(nullptr),
  13. mResizeXWithWidget(false), mResizeYWithWidget(false), mWidth(0), mHeight(0), mRight(0), mBottom(0)
  14. {
  15. switch (layoutType)
  16. {
  17. case GUILayoutType::LayoutX:
  18. mLayout = bs_new<GUILayoutX>(this);
  19. break;
  20. case GUILayoutType::LayoutY:
  21. mLayout = bs_new<GUILayoutY>(this);
  22. break;
  23. case GUILayoutType::LayoutExplicit:
  24. mLayout = bs_new<GUILayoutExplicit>(this);
  25. break;
  26. }
  27. mLayout->_changeParentWidget(widget);
  28. mWidget->registerArea(this);
  29. }
  30. GUIArea::~GUIArea()
  31. {
  32. bs_delete(mLayout);
  33. }
  34. GUIArea* GUIArea::create(GUIWidget& widget, INT32 x, INT32 y, UINT32 width, UINT32 height,
  35. UINT16 depth, GUILayoutType layoutType)
  36. {
  37. GUIArea* area = new (bs_alloc<GUIArea, PoolAlloc>()) GUIArea(&widget, x, y, depth, layoutType);
  38. area->mWidth = width;
  39. area->mHeight = height;
  40. return area;
  41. }
  42. GUIArea* GUIArea::createStretchedXY(GUIWidget& widget, UINT32 offsetLeft,
  43. UINT32 offsetRight, UINT32 offsetTop, UINT32 offsetBottom, UINT16 depth, GUILayoutType layoutType)
  44. {
  45. GUIArea* area = new (bs_alloc<GUIArea, PoolAlloc>()) GUIArea(&widget, offsetLeft, offsetTop, depth, layoutType);
  46. area->mWidth = std::max(0, (INT32)widget.getTarget()->getWidth() - (INT32)offsetLeft - (INT32)offsetRight);
  47. area->mHeight = std::max(0, (INT32)widget.getTarget()->getHeight() - (INT32)offsetTop - (INT32)offsetBottom);
  48. area->mRight = offsetRight;
  49. area->mBottom = offsetBottom;
  50. area->mResizeXWithWidget = true;
  51. area->mResizeYWithWidget = true;
  52. return area;
  53. }
  54. GUIArea* GUIArea::createStretchedX(GUIWidget& widget, UINT32 offsetLeft,
  55. UINT32 offsetRight, UINT32 offsetTop, UINT32 height, UINT16 depth, GUILayoutType layoutType)
  56. {
  57. GUIArea* area = new (bs_alloc<GUIArea, PoolAlloc>()) GUIArea(&widget, offsetLeft, offsetTop, depth, layoutType);
  58. area->mWidth = std::max(0, (INT32)widget.getTarget()->getWidth() - (INT32)offsetLeft - (INT32)offsetRight);
  59. area->mHeight = height;
  60. area->mRight = offsetRight;
  61. area->mResizeXWithWidget = true;
  62. area->mResizeYWithWidget = false;
  63. return area;
  64. }
  65. GUIArea* GUIArea::createStretchedY(GUIWidget& widget, UINT32 offsetTop,
  66. UINT32 offsetBottom, UINT32 offsetLeft, UINT32 width, UINT16 depth, GUILayoutType layoutType)
  67. {
  68. GUIArea* area = new (bs_alloc<GUIArea, PoolAlloc>()) GUIArea(&widget, offsetLeft, offsetTop, depth, layoutType);
  69. area->mWidth = width;
  70. area->mHeight = std::max(0, (INT32)widget.getTarget()->getHeight() - (INT32)offsetTop - (INT32)offsetBottom);
  71. area->mBottom = offsetBottom;
  72. area->mResizeXWithWidget = false;
  73. area->mResizeYWithWidget = true;
  74. return area;
  75. }
  76. void GUIArea::destroy(GUIArea* area)
  77. {
  78. if(area->mWidget != nullptr)
  79. area->mWidget->unregisterArea(area);
  80. bs_delete<PoolAlloc>(area);
  81. }
  82. void GUIArea::destroyInternal(GUIArea* area)
  83. {
  84. bs_delete<PoolAlloc>(area);
  85. }
  86. void GUIArea::disable()
  87. {
  88. mIsDisabled = true;
  89. mLayout->disableRecursively();
  90. }
  91. void GUIArea::enable()
  92. {
  93. mIsDisabled = false;
  94. mLayout->enableRecursively();
  95. }
  96. void GUIArea::changeParentWidget(GUIWidget* widget)
  97. {
  98. if(mWidget == widget)
  99. return;
  100. if(mWidget != nullptr)
  101. mWidget->unregisterArea(this);
  102. if(widget != nullptr)
  103. widget->registerArea(this);
  104. mWidget = widget;
  105. mLayout->_changeParentWidget(widget);
  106. if(mWidget != nullptr)
  107. {
  108. // Ensure the size is valid, otherwise next GUI layout update will calculate wrong element coordinates
  109. updateSizeBasedOnParent(mWidget->getTarget()->getWidth(), mWidget->getTarget()->getHeight());
  110. }
  111. mIsDirty = true;
  112. }
  113. void GUIArea::_update()
  114. {
  115. if(!mIsDisabled && isDirty() && (mWidget != nullptr))
  116. {
  117. Rect2I clipRect(mLeft, mTop, mWidth, mHeight);
  118. if (mClipRect.width > 0 && mClipRect.height > 0)
  119. {
  120. Rect2I newClipRect = Rect2I(mLeft + mClipRect.x, mTop + mClipRect.y, mClipRect.width, mClipRect.height);
  121. newClipRect.clip(clipRect);
  122. clipRect = newClipRect;
  123. }
  124. mLayout->setOffset(Vector2I(mLeft, mTop));
  125. mLayout->setWidth(mWidth);
  126. mLayout->setHeight(mHeight);
  127. mLayout->_updateLayout(mLeft, mTop, mWidth, mHeight, clipRect, mWidget->getDepth(), mDepth);
  128. mIsDirty = false;
  129. }
  130. }
  131. bool GUIArea::isDirty() const
  132. {
  133. if(mIsDirty)
  134. return true;
  135. return mLayout->_isContentDirty();
  136. }
  137. void GUIArea::setPosition(INT32 x, INT32 y)
  138. {
  139. mLeft = x;
  140. mTop = y;
  141. mIsDirty = true;
  142. }
  143. void GUIArea::setSize(UINT32 width, UINT32 height)
  144. {
  145. mWidth = width;
  146. mHeight = height;
  147. mIsDirty = true;
  148. }
  149. void GUIArea::setClipRect(const Rect2I& clipRect)
  150. {
  151. mClipRect = clipRect;
  152. mIsDirty = true;
  153. }
  154. void GUIArea::updateSizeBasedOnParent(UINT32 parentWidth, UINT32 parentHeight)
  155. {
  156. if(mResizeXWithWidget)
  157. mWidth = (UINT32)std::max(0, (INT32)parentWidth - (INT32)mLeft - (INT32)mRight);
  158. if(mResizeYWithWidget)
  159. mHeight = (UINT32)std::max(0, (INT32)parentHeight - (INT32)mTop - (INT32)mBottom);
  160. if(mResizeXWithWidget || mResizeYWithWidget)
  161. mIsDirty = true;
  162. }
  163. }