BsGUIElement.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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. mLayoutData.depth = depth | (mLayoutData.depth & 0xFFFFFF00);
  51. _markMeshAsDirty();
  52. }
  53. void GUIElement::_setLayoutData(const GUILayoutData& data)
  54. {
  55. GUIElementBase::_setLayoutData(data);
  56. updateClippedBounds();
  57. }
  58. void GUIElement::_changeParentWidget(GUIWidget* widget)
  59. {
  60. bool doRefreshStyle = false;
  61. if(mParentWidget != widget)
  62. doRefreshStyle = true;
  63. GUIElementBase::_changeParentWidget(widget);
  64. if(doRefreshStyle)
  65. _refreshStyle();
  66. }
  67. const RectOffset& GUIElement::_getPadding() const
  68. {
  69. if(mStyle != nullptr)
  70. return mStyle->padding;
  71. else
  72. {
  73. static RectOffset padding;
  74. return padding;
  75. }
  76. }
  77. void GUIElement::setFocus(bool enabled)
  78. {
  79. GUIManager::instance().setFocus(this, enabled);
  80. }
  81. void GUIElement::resetDimensions()
  82. {
  83. mDimensions = GUIDimensions::create();
  84. mDimensions.updateWithStyle(mStyle);
  85. _markContentAsDirty();
  86. }
  87. Rect2I GUIElement::getCachedVisibleBounds() const
  88. {
  89. Rect2I bounds = _getClippedBounds();
  90. bounds.x += mStyle->margins.left;
  91. bounds.y += mStyle->margins.top;
  92. bounds.width = (UINT32)std::max(0, (INT32)bounds.width - (INT32)(mStyle->margins.left + mStyle->margins.right));
  93. bounds.height = (UINT32)std::max(0, (INT32)bounds.height - (INT32)(mStyle->margins.top + mStyle->margins.bottom));
  94. return bounds;
  95. }
  96. Rect2I GUIElement::getCachedContentBounds() const
  97. {
  98. Rect2I bounds;
  99. bounds.x = mLayoutData.area.x + mStyle->margins.left + mStyle->contentOffset.left;
  100. bounds.y = mLayoutData.area.y + mStyle->margins.top + mStyle->contentOffset.top;
  101. bounds.width = (UINT32)std::max(0, (INT32)mLayoutData.area.width -
  102. (INT32)(mStyle->margins.left + mStyle->margins.right + mStyle->contentOffset.left + mStyle->contentOffset.right));
  103. bounds.height = (UINT32)std::max(0, (INT32)mLayoutData.area.height -
  104. (INT32)(mStyle->margins.top + mStyle->margins.bottom + mStyle->contentOffset.top + mStyle->contentOffset.bottom));
  105. return bounds;
  106. }
  107. Rect2I GUIElement::getCachedContentClipRect() const
  108. {
  109. Rect2I contentBounds = getCachedContentBounds();
  110. // Transform into element space so we can clip it using the element clip rectangle
  111. Vector2I offsetDiff = Vector2I(contentBounds.x - mLayoutData.area.x, contentBounds.y - mLayoutData.area.y);
  112. Rect2I contentClipRect(offsetDiff.x, offsetDiff.y, contentBounds.width, contentBounds.height);
  113. contentClipRect.clip(mLayoutData.getLocalClipRect());
  114. // Transform into content sprite space
  115. contentClipRect.x -= offsetDiff.x;
  116. contentClipRect.y -= offsetDiff.y;
  117. return contentClipRect;
  118. }
  119. bool GUIElement::_isInBounds(const Vector2I position) const
  120. {
  121. Rect2I contentBounds = getCachedVisibleBounds();
  122. return contentBounds.contains(position);
  123. }
  124. void GUIElement::_refreshStyle()
  125. {
  126. const GUIElementStyle* newStyle = nullptr;
  127. if(_getParentWidget() != nullptr && !mStyleName.empty())
  128. newStyle = _getParentWidget()->getSkin().getStyle(mStyleName);
  129. else
  130. newStyle = &GUISkin::DefaultStyle;
  131. if(newStyle != mStyle)
  132. {
  133. mStyle = newStyle;
  134. mDimensions.updateWithStyle(mStyle);
  135. styleUpdated();
  136. _markContentAsDirty();
  137. }
  138. }
  139. const String& GUIElement::getSubStyleName(const String& subStyleTypeName) const
  140. {
  141. auto iterFind = mStyle->subStyles.find(subStyleTypeName);
  142. if (iterFind != mStyle->subStyles.end())
  143. return iterFind->second;
  144. else
  145. return StringUtil::BLANK;
  146. }
  147. void GUIElement::destroy(GUIElement* element)
  148. {
  149. if(element->mIsDestroyed)
  150. return;
  151. if (element->mParentElement != nullptr)
  152. element->mParentElement->_unregisterChildElement(element);
  153. element->mIsDestroyed = true;
  154. GUIManager::instance().queueForDestroy(element);
  155. }
  156. Rect2I GUIElement::getVisibleBounds()
  157. {
  158. Rect2I bounds = getBounds();
  159. bounds.x += mStyle->margins.left;
  160. bounds.y += mStyle->margins.top;
  161. bounds.width = (UINT32)std::max(0, (INT32)bounds.width - (INT32)(mStyle->margins.left + mStyle->margins.right));
  162. bounds.height = (UINT32)std::max(0, (INT32)bounds.height - (INT32)(mStyle->margins.top + mStyle->margins.bottom));
  163. return bounds;
  164. }
  165. }