BsGUIElement.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #include "BsGUIElement.h"
  2. #include "BsGUIWidget.h"
  3. #include "BsGUISkin.h"
  4. #include "BsGUILayout.h"
  5. #include "BsGUIManager.h"
  6. #include "BsException.h"
  7. #include "BsGUILayoutUtility.h"
  8. namespace BansheeEngine
  9. {
  10. GUIElement::GUIElement(const String& styleName, const GUIDimensions& dimensions)
  11. :GUIElementBase(dimensions), mStyle(&GUISkin::DefaultStyle),
  12. mIsDestroyed(false), mStyleName(styleName)
  13. {
  14. // Style is set to default here, and the proper one is assigned once GUI element
  15. // is assigned to a parent (that's when the active GUI skin becomes known)
  16. }
  17. GUIElement::~GUIElement()
  18. { }
  19. void GUIElement::_updateRenderElements()
  20. {
  21. updateRenderElementsInternal();
  22. }
  23. void GUIElement::updateRenderElementsInternal()
  24. {
  25. updateClippedBounds();
  26. }
  27. void GUIElement::setStyle(const String& styleName)
  28. {
  29. mStyleName = styleName;
  30. _refreshStyle();
  31. }
  32. bool GUIElement::_mouseEvent(const GUIMouseEvent& ev)
  33. {
  34. return false;
  35. }
  36. bool GUIElement::_textInputEvent(const GUITextInputEvent& ev)
  37. {
  38. return false;
  39. }
  40. bool GUIElement::_commandEvent(const GUICommandEvent& ev)
  41. {
  42. return false;
  43. }
  44. bool GUIElement::_virtualButtonEvent(const GUIVirtualButtonEvent& ev)
  45. {
  46. return false;
  47. }
  48. void GUIElement::_setElementDepth(UINT8 depth)
  49. {
  50. mDepth = depth | (mDepth & 0xFFFFFF00);
  51. markMeshAsDirty();
  52. }
  53. void GUIElement::_setClipRect(const Rect2I& clipRect)
  54. {
  55. if(mClipRect != clipRect)
  56. {
  57. mClipRect = clipRect;
  58. updateClippedBounds();
  59. }
  60. }
  61. void GUIElement::_changeParentWidget(GUIWidget* widget)
  62. {
  63. bool doRefreshStyle = false;
  64. if(mParentWidget != widget)
  65. doRefreshStyle = true;
  66. GUIElementBase::_changeParentWidget(widget);
  67. if(doRefreshStyle)
  68. _refreshStyle();
  69. }
  70. const RectOffset& GUIElement::_getPadding() const
  71. {
  72. if(mStyle != nullptr)
  73. return mStyle->padding;
  74. else
  75. {
  76. static RectOffset padding;
  77. return padding;
  78. }
  79. }
  80. Rect2I GUIElement::_getCachedBounds() const
  81. {
  82. return Rect2I(mOffset.x, mOffset.y, mWidth, mHeight);
  83. }
  84. void GUIElement::setFocus(bool enabled)
  85. {
  86. GUIManager::instance().setFocus(this, enabled);
  87. }
  88. void GUIElement::resetDimensions()
  89. {
  90. mDimensions = GUIDimensions::create();
  91. mDimensions.updateWithStyle(mStyle);
  92. markContentAsDirty();
  93. }
  94. Rect2I GUIElement::getCachedVisibleBounds() const
  95. {
  96. Rect2I bounds = _getClippedBounds();
  97. bounds.x += mStyle->margins.left;
  98. bounds.y += mStyle->margins.top;
  99. bounds.width = (UINT32)std::max(0, (INT32)bounds.width - (INT32)(mStyle->margins.left + mStyle->margins.right));
  100. bounds.height = (UINT32)std::max(0, (INT32)bounds.height - (INT32)(mStyle->margins.top + mStyle->margins.bottom));
  101. return bounds;
  102. }
  103. Rect2I GUIElement::getCachedContentBounds() const
  104. {
  105. Rect2I bounds;
  106. bounds.x = mOffset.x + mStyle->margins.left + mStyle->contentOffset.left;
  107. bounds.y = mOffset.y + mStyle->margins.top + mStyle->contentOffset.top;
  108. bounds.width = (UINT32)std::max(0, (INT32)mWidth -
  109. (INT32)(mStyle->margins.left + mStyle->margins.right + mStyle->contentOffset.left + mStyle->contentOffset.right));
  110. bounds.height = (UINT32)std::max(0, (INT32)mHeight -
  111. (INT32)(mStyle->margins.top + mStyle->margins.bottom + mStyle->contentOffset.top + mStyle->contentOffset.bottom));
  112. return bounds;
  113. }
  114. Rect2I GUIElement::getCachedContentClipRect() const
  115. {
  116. Rect2I contentBounds = getCachedContentBounds();
  117. // Transform into element space so we can clip it using the element clip rectangle
  118. Vector2I offsetDiff = Vector2I(contentBounds.x - mOffset.x, contentBounds.y - mOffset.y);
  119. Rect2I contentClipRect(offsetDiff.x, offsetDiff.y, contentBounds.width, contentBounds.height);
  120. contentClipRect.clip(mClipRect);
  121. // Transform into content sprite space
  122. contentClipRect.x -= offsetDiff.x;
  123. contentClipRect.y -= offsetDiff.y;
  124. return contentClipRect;
  125. }
  126. bool GUIElement::_isInBounds(const Vector2I position) const
  127. {
  128. Rect2I contentBounds = getCachedVisibleBounds();
  129. return contentBounds.contains(position);
  130. }
  131. void GUIElement::_refreshStyle()
  132. {
  133. const GUIElementStyle* newStyle = nullptr;
  134. if(_getParentWidget() != nullptr && !mStyleName.empty())
  135. newStyle = _getParentWidget()->getSkin().getStyle(mStyleName);
  136. else
  137. newStyle = &GUISkin::DefaultStyle;
  138. if(newStyle != mStyle)
  139. {
  140. mStyle = newStyle;
  141. mDimensions.updateWithStyle(mStyle);
  142. styleUpdated();
  143. markContentAsDirty();
  144. }
  145. }
  146. const String& GUIElement::getSubStyleName(const String& subStyleTypeName) const
  147. {
  148. auto iterFind = mStyle->subStyles.find(subStyleTypeName);
  149. if (iterFind != mStyle->subStyles.end())
  150. return iterFind->second;
  151. else
  152. return StringUtil::BLANK;
  153. }
  154. void GUIElement::destroy(GUIElement* element)
  155. {
  156. if(element->mIsDestroyed)
  157. return;
  158. if (element->mParentElement != nullptr)
  159. element->mParentElement->_unregisterChildElement(element);
  160. element->mIsDestroyed = true;
  161. GUIManager::instance().queueForDestroy(element);
  162. }
  163. Rect2I GUIElement::getVisibleBounds() const
  164. {
  165. Rect2I bounds = getBounds();
  166. bounds.x += mStyle->margins.left;
  167. bounds.y += mStyle->margins.top;
  168. bounds.width = (UINT32)std::max(0, (INT32)bounds.width - (INT32)(mStyle->margins.left + mStyle->margins.right));
  169. bounds.height = (UINT32)std::max(0, (INT32)bounds.height - (INT32)(mStyle->margins.top + mStyle->margins.bottom));
  170. return bounds;
  171. }
  172. }