BsGUIElementBase.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsPrerequisites.h"
  5. #include "BsGUIDimensions.h"
  6. #include "BsGUILayoutData.h"
  7. #include "BsRect2I.h"
  8. #include "BsVector2I.h"
  9. #include "BsRectOffset.h"
  10. namespace BansheeEngine
  11. {
  12. /** @addtogroup Implementation
  13. * @{
  14. */
  15. /** Base class for all GUI elements (visible or layout). */
  16. class BS_EXPORT GUIElementBase
  17. {
  18. public:
  19. /** Valid types of GUI base elements. */
  20. enum class Type
  21. {
  22. Layout,
  23. Element,
  24. FixedSpace,
  25. FlexibleSpace,
  26. Panel
  27. };
  28. protected:
  29. /** Flags that signal the state of the GUI element. */
  30. enum GUIElementFlags
  31. {
  32. GUIElem_Dirty = 0x01,
  33. GUIElem_Hidden = 0x02,
  34. GUIElem_Inactive = 0x04,
  35. GUIElem_HiddenSelf = 0x08,
  36. GUIElem_InactiveSelf = 0x10,
  37. GUIElem_Disabled = 0x20,
  38. GUIElem_DisabledSelf = 0x40
  39. };
  40. public:
  41. GUIElementBase();
  42. GUIElementBase(const GUIDimensions& dimensions);
  43. virtual ~GUIElementBase();
  44. /**
  45. * Sets element position relative to parent GUI panel.
  46. *
  47. * @note
  48. * Be aware that this value will be ignored if GUI element is part of a layout since then the layout controls its
  49. * placement.
  50. */
  51. void setPosition(INT32 x, INT32 y);
  52. /** Sets element width in pixels. */
  53. void setWidth(UINT32 width);
  54. /**
  55. * Sets element width in pixels. Element will be resized according to its contents and parent layout but will
  56. * always stay within the provided range. If maximum width is zero, the element is allowed to expand as much as
  57. * it needs.
  58. */
  59. void setFlexibleWidth(UINT32 minWidth = 0, UINT32 maxWidth = 0);
  60. /** Sets element height in pixels. */
  61. void setHeight(UINT32 height);
  62. /**
  63. * Sets element height in pixels. Element will be resized according to its contents and parent layout but will
  64. * always stay within the provided range. If maximum height is zero, the element is allowed to expand as much as
  65. * it needs.
  66. */
  67. void setFlexibleHeight(UINT32 minHeight = 0, UINT32 maxHeight = 0);
  68. /** Resets element dimensions to their initial values dictated by the element's style. */
  69. virtual void resetDimensions();
  70. /**
  71. * Hides or shows this element and recursively applies the same state to all the child elements. This will not
  72. * remove the element from the layout, the room for it will still be reserved but it just won't be visible.
  73. */
  74. void setVisible(bool visible);
  75. /**
  76. * Activates or deactives this element and recursively applies the same state to all the child elements. This has
  77. * the same effect as setVisible(), but when disabled it will also remove the element from the layout, essentially
  78. * having the same effect is if you destroyed the element.
  79. */
  80. void setActive(bool active);
  81. /** Disables or enables the element. Disabled elements cannot be interacted with and have a faded out appearance. */
  82. void setDisabled(bool disabled);
  83. /**
  84. * Returns non-clipped bounds of the GUI element. Relative to a parent GUI panel.
  85. *
  86. * @param[in] relativeTo Parent panel of the provided element relative to which to return the bounds. If null
  87. * the bounds relative to the first parent panel are returned. Behavior is undefined if
  88. * provided panel is not a parent of the element.
  89. *
  90. * @note This call can be potentially expensive if the GUI state is dirty.
  91. */
  92. Rect2I getBounds(GUIPanel* relativeTo = nullptr);
  93. /**
  94. * Sets the bounds of the GUI element. Relative to a parent GUI panel. Equivalent to calling setPosition(),
  95. * setWidth() and setHeight().
  96. */
  97. void setBounds(const Rect2I& bounds);
  98. /**
  99. * Returns non-clipped bounds of the GUI element. Relative to a parent GUI widget.
  100. *
  101. * @note This call can be potentially expensive if the GUI state is dirty.
  102. */
  103. Rect2I getGlobalBounds();
  104. /**
  105. * Returns non-clipped visible bounds of the GUI element (bounds exclude the margins). Relative to the parent GUI
  106. * panel.
  107. *
  108. * @note This call can be potentially expensive as the bounds need to be calculated based on current GUI state.
  109. */
  110. virtual Rect2I getVisibleBounds();
  111. public: // ***** INTERNAL ******
  112. /** @name Internal
  113. * @{
  114. */
  115. /**
  116. * Updates child elements positions, sizes, clip rectangles and depths so they fit into the provided bounds, while
  117. * respecting their layout options.
  118. *
  119. * @param[in] data Layout data containing the necessary bounds and restrictions to use for calculating the
  120. * child element layout data.
  121. *
  122. * @note Internal method.
  123. */
  124. virtual void _updateLayout(const GUILayoutData& data);
  125. /** Calculates optimal sizes of all child elements, as determined by their style and layout options. */
  126. virtual void _updateOptimalLayoutSizes();
  127. /** @copydoc _updateLayout */
  128. virtual void _updateLayoutInternal(const GUILayoutData& data);
  129. /**
  130. * Calculates positions & sizes of all elements in the layout. This method expects a pre-allocated array to store
  131. * the data in.
  132. *
  133. * @param[in] layoutArea Parent layout area to position the child elements in.
  134. * @param[out] elementAreas Array to hold output areas. Must be the same size as the number of child elements.
  135. * @param[in] numElements Size of the element areas array.
  136. * @param[in] sizeRanges Ranges of possible sizes used for the child elements. Array must be same size as
  137. * elements array.
  138. * @param[in] mySizeRange Size range of this element.
  139. */
  140. virtual void _getElementAreas(const Rect2I& layoutArea, Rect2I* elementAreas, UINT32 numElements,
  141. const Vector<LayoutSizeRange>& sizeRanges, const LayoutSizeRange& mySizeRange) const;
  142. /** Updates layout data that determines GUI elements final position & depth in the GUI widget. */
  143. virtual void _setLayoutData(const GUILayoutData& data) { mLayoutData = data; }
  144. /** Retrieves layout data that determines GUI elements final position & depth in the GUI widget. */
  145. const GUILayoutData& _getLayoutData() const { return mLayoutData; }
  146. /** Sets a new parent for this element. */
  147. void _setParent(GUIElementBase* parent);
  148. /** Returns number of child elements. */
  149. UINT32 _getNumChildren() const { return (UINT32)mChildren.size(); }
  150. /** Return the child element at the specified index.*/
  151. GUIElementBase* _getChild(UINT32 idx) const { return mChildren[idx]; }
  152. /** Returns previously calculated optimal size for this element. */
  153. virtual Vector2I _getOptimalSize() const = 0;
  154. /** Returns layout options that determine how is the element positioned and sized. */
  155. const GUIDimensions& _getDimensions() const { return mDimensions; }
  156. /** Calculates element size range constrained by its layout options. */
  157. virtual LayoutSizeRange _calculateLayoutSizeRange() const ;
  158. /**
  159. * Returns element size range constrained by its layout options. This is different from _calculateLayoutSizeRange()
  160. * because this method may return cached size range.
  161. */
  162. virtual LayoutSizeRange _getLayoutSizeRange() const;
  163. /**
  164. * Returns element padding that determines how far apart to space out this element from other elements in a layout.
  165. */
  166. virtual const RectOffset& _getPadding() const = 0;
  167. /** Returns specific sub-type of this object. */
  168. virtual Type _getType() const = 0;
  169. /** Returns parent GUI base element. */
  170. GUIElementBase* _getParent() const { return mParentElement; }
  171. /**
  172. * Returns the parent element whose layout needs to be updated when this elements contents change.
  173. *
  174. * @note
  175. * Due to the nature of the GUI system, when a child element bounds or contents change, its parents and siblings
  176. * usually need their layout bound updated. This function returns the first parent of all the elements that require
  177. * updating. This parent usually has fixed bounds or some other property that allows its children to be updated
  178. * independently from the even higher-up elements.
  179. */
  180. GUIElementBase* _getUpdateParent() const { return mUpdateParent; }
  181. /** Returns parent GUI widget, can be null. */
  182. GUIWidget* _getParentWidget() const { return mParentWidget; }
  183. /** Checks if element is visible or hidden. */
  184. bool _isVisible() const { return (mFlags & GUIElem_Hidden) == 0; }
  185. /**
  186. * Checks if element is active or inactive. Inactive elements are not visible, don't take up space
  187. * in their parent layouts, and can't be interacted with.
  188. */
  189. bool _isActive() const { return (mFlags & GUIElem_Inactive) == 0; }
  190. /** Checks if element is disabled. Disabled elements cannot be interacted with and have a faded out appearance. */
  191. bool _isDisabled() const { return (mFlags & GUIElem_Disabled) != 0; }
  192. /**
  193. * Internal version of setVisible() that doesn't modify local visibility, instead it is only meant to be called
  194. * on child elements of the element whose visibility was modified.
  195. */
  196. void _setVisible(bool visible);
  197. /**
  198. * Internal version of setActive() that doesn't modify local state, instead it is only meant to be called
  199. * on child elements of the element whose state was modified.
  200. *
  201. * @copydoc setActive
  202. */
  203. void _setActive(bool active);
  204. /**
  205. * Internal version of setDisabled() that doesn't modify local state, instead it is only meant to be called
  206. * on child elements of the element whose state was modified.
  207. *
  208. * @copydoc setDisabled
  209. */
  210. void _setDisabled(bool disabled);
  211. /**
  212. * Changes the active GUI element widget. This allows you to move an element to a different viewport, or change
  213. * element style by using a widget with a different skin. You are allowed to pass null here, but elements with no
  214. * parent will be unmanaged. You will be responsible for deleting them manually, and they will not render anywhere.
  215. */
  216. virtual void _changeParentWidget(GUIWidget* widget);
  217. /**Registers a new child element. */
  218. void _registerChildElement(GUIElementBase* element);
  219. /** Unregisters an existing child element. */
  220. void _unregisterChildElement(GUIElementBase* element);
  221. /** Checks if element has been destroyed and is queued for deletion. */
  222. virtual bool _isDestroyed() const { return false; }
  223. /** Marks the element's dimensions as dirty, triggering a layout rebuild. */
  224. void _markLayoutAsDirty();
  225. /** Marks the element's contents as dirty, which causes the sprite meshes to be recreated from scratch. */
  226. void _markContentAsDirty();
  227. /**
  228. * Mark only the elements that operate directly on the sprite mesh without requiring the mesh to be recreated as
  229. * dirty. This includes position, depth and clip rectangle. This will cause the parent widget mesh to be rebuilt
  230. * from its child element's meshes.
  231. */
  232. void _markMeshAsDirty();
  233. /** Returns true if elements contents have changed since last update. */
  234. bool _isDirty() const { return (mFlags & GUIElem_Dirty) != 0; }
  235. /** Marks the element contents to be up to date (meaning it's processed by the GUI system). */
  236. void _markAsClean();
  237. /** @} */
  238. protected:
  239. /** Finds anchor and update parents and recursively assigns them to all children. */
  240. void _updateAUParents();
  241. /** Refreshes update parents of all child elements. */
  242. void refreshChildUpdateParents();
  243. /**
  244. * Finds the first parent element whose size doesn't depend on child sizes.
  245. *
  246. * @note
  247. * This allows us to optimize layout updates and trigger them only on such parents when their child elements
  248. * contents change, compared to doing them on the entire GUI hierarchy.
  249. */
  250. GUIElementBase* findUpdateParent();
  251. /**
  252. * Helper method for recursion in _updateAUParents(). Sets the provided anchor parent for all children recursively.
  253. * Recursion stops when a child anchor is detected.
  254. */
  255. void setAnchorParent(GUIPanel* anchorParent);
  256. /**
  257. * Helper method for recursion in _updateAUParents(). Sets the provided update parent for all children recursively.
  258. * Recursion stops when a child update parent is detected.
  259. */
  260. void setUpdateParent(GUIElementBase* updateParent);
  261. GUIWidget* mParentWidget;
  262. GUIPanel* mAnchorParent;
  263. GUIElementBase* mUpdateParent;
  264. GUIElementBase* mParentElement;
  265. Vector<GUIElementBase*> mChildren;
  266. UINT8 mFlags;
  267. GUIDimensions mDimensions;
  268. GUILayoutData mLayoutData;
  269. };
  270. /** @} */
  271. }