UIElement.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. /// \file
  4. #pragma once
  5. #include "../Math/Vector2.h"
  6. #include "../Input/InputConstants.h"
  7. #include "../Resource/XMLFile.h"
  8. #include "../Scene/Animatable.h"
  9. #include "../UI/UIBatch.h"
  10. namespace Urho3D
  11. {
  12. /// %UI element horizontal alignment.
  13. enum HorizontalAlignment
  14. {
  15. HA_LEFT = 0,
  16. HA_CENTER,
  17. HA_RIGHT,
  18. HA_CUSTOM
  19. };
  20. /// %UI element vertical alignment.
  21. enum VerticalAlignment
  22. {
  23. VA_TOP = 0,
  24. VA_CENTER,
  25. VA_BOTTOM,
  26. VA_CUSTOM
  27. };
  28. /// %UI element corners.
  29. enum Corner
  30. {
  31. C_TOPLEFT = 0,
  32. C_TOPRIGHT,
  33. C_BOTTOMLEFT,
  34. C_BOTTOMRIGHT,
  35. MAX_UIELEMENT_CORNERS
  36. };
  37. /// %UI element orientation.
  38. enum Orientation
  39. {
  40. O_HORIZONTAL = 0,
  41. O_VERTICAL
  42. };
  43. /// %UI element focus mode.
  44. enum FocusMode
  45. {
  46. /// Is not focusable and does not affect existing focus.
  47. FM_NOTFOCUSABLE = 0,
  48. /// Resets focus when clicked.
  49. FM_RESETFOCUS,
  50. /// Is focusable.
  51. FM_FOCUSABLE,
  52. /// Is focusable and also defocusable by pressing ESC.
  53. FM_FOCUSABLE_DEFOCUSABLE
  54. };
  55. /// Layout operation mode.
  56. enum LayoutMode
  57. {
  58. /// No layout operations will be performed.
  59. LM_FREE = 0,
  60. /// Layout child elements horizontally and resize them to fit. Resize element if necessary.
  61. LM_HORIZONTAL,
  62. /// Layout child elements vertically and resize them to fit. Resize element if necessary.
  63. LM_VERTICAL
  64. };
  65. /// Traversal mode for rendering.
  66. enum TraversalMode
  67. {
  68. /// Traverse through children having same priority first and recurse into their children before traversing children having higher priority.
  69. TM_BREADTH_FIRST = 0,
  70. /// Traverse through each child and its children immediately after in sequence.
  71. TM_DEPTH_FIRST
  72. };
  73. enum DragAndDropMode : unsigned
  74. {
  75. /// Drag and drop disabled.
  76. DD_DISABLED = 0x0,
  77. /// Drag and drop source flag.
  78. DD_SOURCE = 0x1,
  79. /// Drag and drop target flag.
  80. DD_TARGET = 0x2,
  81. /// Drag and drop source and target.
  82. DD_SOURCE_AND_TARGET = 0x3,
  83. };
  84. URHO3D_FLAGSET(DragAndDropMode, DragAndDropModeFlags);
  85. class Cursor;
  86. class ResourceCache;
  87. class Texture2D;
  88. /// Base class for %UI elements.
  89. class URHO3D_API UIElement : public Animatable
  90. {
  91. URHO3D_OBJECT(UIElement, Animatable);
  92. public:
  93. /// Construct.
  94. explicit UIElement(Context* context);
  95. /// Destruct.
  96. ~UIElement() override;
  97. /// Register object factory.
  98. /// @nobind
  99. static void RegisterObject(Context* context);
  100. /// Apply attribute changes that can not be applied immediately.
  101. void ApplyAttributes() override;
  102. /// Load from XML data. Return true if successful.
  103. bool LoadXML(const XMLElement& source) override;
  104. /// Load from XML data with style. Return true if successful.
  105. virtual bool LoadXML(const XMLElement& source, XMLFile* styleFile);
  106. /// Create a child by loading from XML data with style. Returns the child element if successful, null if otherwise.
  107. virtual UIElement* LoadChildXML(const XMLElement& childElem, XMLFile* styleFile);
  108. /// Save as XML data. Return true if successful.
  109. bool SaveXML(XMLElement& dest) const override;
  110. /// Perform UI element update.
  111. virtual void Update(float timeStep);
  112. /// Return whether is visible and inside a scissor rectangle and should be rendered.
  113. virtual bool IsWithinScissor(const IntRect& currentScissor);
  114. /// Update and return screen position.
  115. /// @property
  116. virtual const IntVector2& GetScreenPosition() const;
  117. /// Return UI rendering batches.
  118. virtual void GetBatches(Vector<UIBatch>& batches, Vector<float>& vertexData, const IntRect& currentScissor);
  119. /// Return UI rendering batches for debug draw.
  120. virtual void GetDebugDrawBatches(Vector<UIBatch>& batches, Vector<float>& vertexData, const IntRect& currentScissor);
  121. /// React to mouse hover.
  122. virtual void OnHover(const IntVector2& position, const IntVector2& screenPosition, MouseButtonFlags buttons, QualifierFlags qualifiers, Cursor* cursor);
  123. /// React to mouse click begin.
  124. virtual void OnClickBegin
  125. (const IntVector2& position, const IntVector2& screenPosition, MouseButton button, MouseButtonFlags buttons, QualifierFlags qualifiers, Cursor* cursor) { }
  126. /// React to mouse click end.
  127. virtual void OnClickEnd
  128. (const IntVector2& position, const IntVector2& screenPosition, MouseButton button, MouseButtonFlags buttons, QualifierFlags qualifiers, Cursor* cursor,
  129. UIElement* beginElement) { }
  130. /// React to double mouse click.
  131. virtual void OnDoubleClick
  132. (const IntVector2& position, const IntVector2& screenPosition, MouseButton button, MouseButtonFlags buttons, QualifierFlags qualifiers, Cursor* cursor) { }
  133. /// React to mouse drag begin.
  134. virtual void
  135. OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, MouseButtonFlags buttons, QualifierFlags qualifiers, Cursor* cursor);
  136. /// React to mouse drag motion.
  137. virtual void OnDragMove
  138. (const IntVector2& position, const IntVector2& screenPosition, const IntVector2& deltaPos, MouseButtonFlags buttons, QualifierFlags qualifiers,
  139. Cursor* cursor);
  140. /// React to mouse drag end.
  141. virtual void
  142. OnDragEnd(const IntVector2& position, const IntVector2& screenPosition, MouseButtonFlags dragButtons, MouseButtonFlags releaseButtons, Cursor* cursor);
  143. /// React to a mouse drag cancel event (ie, when an extra button is pressed).
  144. virtual void OnDragCancel
  145. (const IntVector2& position, const IntVector2& screenPosition, MouseButtonFlags dragButtons, MouseButtonFlags cancelButtons, Cursor* cursor);
  146. /// React to drag and drop test. Return true to signal that the drop is acceptable.
  147. virtual bool OnDragDropTest(UIElement* source);
  148. /// React to drag and drop finish. Return true to signal that the drop was accepted.
  149. virtual bool OnDragDropFinish(UIElement* source);
  150. /// React to mouse wheel.
  151. virtual void OnWheel(int delta, MouseButtonFlags buttons, QualifierFlags qualifiers) { }
  152. /// React to a key press.
  153. virtual void OnKey(Key key, MouseButtonFlags buttons, QualifierFlags qualifiers) { }
  154. /// React to text input event.
  155. virtual void OnTextInput(const String& text) { }
  156. /// React to resize.
  157. virtual void OnResize(const IntVector2& newSize, const IntVector2& delta) { }
  158. /// React to position change.
  159. virtual void OnPositionSet(const IntVector2& newPosition) { }
  160. /// React to editable status change.
  161. virtual void OnSetEditable() { }
  162. /// React to indent change.
  163. virtual void OnIndentSet() { }
  164. /// Convert screen coordinates to element coordinates.
  165. virtual IntVector2 ScreenToElement(const IntVector2& screenPosition);
  166. /// Convert element coordinates to screen coordinates.
  167. virtual IntVector2 ElementToScreen(const IntVector2& position);
  168. /// Return whether the element could handle wheel input.
  169. virtual bool IsWheelHandler() const { return false; }
  170. /// Load from an XML file. Return true if successful.
  171. bool LoadXML(Deserializer& source);
  172. /// Save to an XML file. Return true if successful.
  173. bool SaveXML(Serializer& dest, const String& indentation = "\t") const;
  174. /// Filter attributes in serialization process.
  175. bool FilterAttributes(XMLElement& dest) const;
  176. /// Set name.
  177. /// @property
  178. void SetName(const String& name);
  179. /// Set position.
  180. /// @property
  181. void SetPosition(const IntVector2& position);
  182. /// Set position.
  183. void SetPosition(int x, int y);
  184. /// Set size.
  185. /// @property
  186. void SetSize(const IntVector2& size);
  187. /// Set size.
  188. void SetSize(int width, int height);
  189. /// Set width only.
  190. /// @property
  191. void SetWidth(int width);
  192. /// Set height only.
  193. /// @property
  194. void SetHeight(int height);
  195. /// Set minimum size.
  196. /// @property
  197. void SetMinSize(const IntVector2& minSize);
  198. /// Set minimum size.
  199. void SetMinSize(int width, int height);
  200. /// Set minimum width.
  201. /// @property
  202. void SetMinWidth(int width);
  203. /// Set minimum height.
  204. /// @property
  205. void SetMinHeight(int height);
  206. /// Set maximum size.
  207. /// @property
  208. void SetMaxSize(const IntVector2& maxSize);
  209. /// Set maximum size.
  210. void SetMaxSize(int width, int height);
  211. /// Set maximum width.
  212. /// @property
  213. void SetMaxWidth(int width);
  214. /// Set maximum height.
  215. /// @property
  216. void SetMaxHeight(int height);
  217. /// Set fixed size.
  218. void SetFixedSize(const IntVector2& size);
  219. /// Set fixed size.
  220. void SetFixedSize(int width, int height);
  221. /// Set fixed width.
  222. void SetFixedWidth(int width);
  223. /// Set fixed height.
  224. void SetFixedHeight(int height);
  225. /// Set horizontal and vertical alignment.
  226. void SetAlignment(HorizontalAlignment hAlign, VerticalAlignment vAlign);
  227. /// Set horizontal alignment.
  228. /// @property
  229. void SetHorizontalAlignment(HorizontalAlignment align);
  230. /// Set vertical alignment.
  231. /// @property
  232. void SetVerticalAlignment(VerticalAlignment align);
  233. /// Enable automatic positioning & sizing of the element relative to its parent using min/max anchor and min/max offset. Default false.
  234. /// @property
  235. void SetEnableAnchor(bool enable);
  236. /// Set minimum (top left) anchor in relation to the parent element (from 0 to 1). No effect when anchor is not enabled.
  237. /// @property
  238. void SetMinAnchor(const Vector2& anchor);
  239. /// Set minimum anchor.
  240. void SetMinAnchor(float x, float y);
  241. /// Set maximum (bottom right) anchor in relation to the parent element (from 0 to 1). No effect when anchor is not enabled.
  242. /// @property
  243. void SetMaxAnchor(const Vector2& anchor);
  244. /// Set maximum anchor.
  245. void SetMaxAnchor(float x, float y);
  246. /// Set offset of element's top left from the minimum anchor in pixels. No effect when anchor is not enabled.
  247. /// @property
  248. void SetMinOffset(const IntVector2& offset);
  249. /// Set offset of element's bottom right from the maximum anchor in pixels. No effect when anchor is not enabled.
  250. /// @property
  251. void SetMaxOffset(const IntVector2& offset);
  252. /// Set pivot relative to element's size (from 0 to 1, where 0.5 is center). Overrides horizontal & vertical alignment.
  253. /// @property
  254. void SetPivot(const Vector2& pivot);
  255. /// Set pivot relative to element's size (from 0 to 1, where 0.5 is center). Overrides horizontal & vertical alignment.
  256. void SetPivot(float x, float y);
  257. /// Set child element clipping border.
  258. /// @property
  259. void SetClipBorder(const IntRect& rect);
  260. /// Set color on all corners.
  261. /// @property
  262. void SetColor(const Color& color);
  263. /// Set color on one corner.
  264. /// @property{set_colors}
  265. void SetColor(Corner corner, const Color& color);
  266. /// Set priority.
  267. /// @property
  268. void SetPriority(int priority);
  269. /// Set opacity.
  270. /// @property
  271. void SetOpacity(float opacity);
  272. /// Set whether should be brought to front when focused.
  273. /// @property
  274. void SetBringToFront(bool enable);
  275. /// Set whether should be put to background when another element is focused.
  276. /// @property
  277. void SetBringToBack(bool enable);
  278. /// Set whether should clip child elements. Default false.
  279. /// @property
  280. void SetClipChildren(bool enable);
  281. /// Set whether should sort child elements according to priority. Default true.
  282. /// @property
  283. void SetSortChildren(bool enable);
  284. /// Set whether parent elements' opacity affects opacity. Default true.
  285. /// @property
  286. void SetUseDerivedOpacity(bool enable);
  287. /// Set whether reacts to input. Default false, but is enabled by subclasses if applicable.
  288. /// @property
  289. void SetEnabled(bool enable);
  290. /// Set enabled state on self and child elements. Elements' own enabled state is remembered (IsEnabledSelf) and can be restored.
  291. void SetDeepEnabled(bool enable);
  292. /// Reset enabled state to the element's remembered state prior to calling SetDeepEnabled.
  293. void ResetDeepEnabled();
  294. /// Set enabled state on self and child elements. Unlike SetDeepEnabled this does not remember the elements' own enabled state, but overwrites it.
  295. void SetEnabledRecursive(bool enable);
  296. /// Set whether value is editable through input. Not applicable to all elements. Default true.
  297. /// @property
  298. void SetEditable(bool enable);
  299. /// Set whether is focused. Only one element can be focused at a time.
  300. /// @property
  301. void SetFocus(bool enable);
  302. /// Set selected mode. Actual meaning is element dependent, for example constant hover or pressed effect.
  303. /// @property
  304. void SetSelected(bool enable);
  305. /// Set whether is visible. Visibility propagates to child elements.
  306. /// @property
  307. void SetVisible(bool enable);
  308. /// Set focus mode.
  309. /// @property
  310. void SetFocusMode(FocusMode mode);
  311. /// Set drag and drop flags.
  312. /// @property
  313. void SetDragDropMode(DragAndDropModeFlags mode);
  314. /// Set style from an XML file. Find the style element by name. If the style file is not explicitly provided, use the default style from parental chain. Return true if the style is applied successfully. See also \ref UI_Programmatic.
  315. bool SetStyle(const String& styleName, XMLFile* file = nullptr);
  316. /// Set style from an XML element. Return true if the style is applied successfully.
  317. bool SetStyle(const XMLElement& element);
  318. /// Set style from an XML file. Find the style element automatically by using the element's typename. If the style file is not explicitly provided, use the default style from parental chain. Return true if the style is applied successfully. See also \ref UI_Programmatic.
  319. bool SetStyleAuto(XMLFile* file = nullptr);
  320. /// Set default style file for later use by children elements.
  321. /// @property
  322. void SetDefaultStyle(XMLFile* style);
  323. /// Set layout parameters.
  324. void SetLayout(LayoutMode mode, int spacing = 0, const IntRect& border = IntRect::ZERO);
  325. /// Set layout mode only.
  326. /// @property
  327. void SetLayoutMode(LayoutMode mode);
  328. /// Set layout spacing.
  329. /// @property
  330. void SetLayoutSpacing(int spacing);
  331. /// Set layout border.
  332. /// @property
  333. void SetLayoutBorder(const IntRect& border);
  334. /// Set layout flex scale.
  335. /// @property
  336. void SetLayoutFlexScale(const Vector2& scale);
  337. /// Set horizontal indentation.
  338. /// @property
  339. void SetIndent(int indent);
  340. /// Set indent spacing (number of pixels per indentation level).
  341. /// @property
  342. void SetIndentSpacing(int indentSpacing);
  343. /// Manually update layout. Should not be necessary in most cases, but is provided for completeness.
  344. void UpdateLayout();
  345. /// Disable automatic layout update. Should only be used if there are performance problems.
  346. void DisableLayoutUpdate();
  347. /// Enable automatic layout update.
  348. void EnableLayoutUpdate();
  349. /// Bring UI element to front.
  350. void BringToFront();
  351. /// Create and add a child element and return it.
  352. UIElement* CreateChild(StringHash type, const String& name = String::EMPTY, i32 index = ENDPOS);
  353. /// Add a child element.
  354. void AddChild(UIElement* element);
  355. /// Insert a child element into a specific position in the child list. index can be ENDPOS.
  356. void InsertChild(i32 index, UIElement* element);
  357. /// Remove a child element. Starting search at specified index if provided.
  358. void RemoveChild(UIElement* element, i32 index = 0);
  359. /// Remove a child element at index.
  360. void RemoveChildAtIndex(i32 index);
  361. /// Remove all child elements.
  362. void RemoveAllChildren();
  363. /// Remove from the parent element. If no other shared pointer references exist, causes immediate deletion.
  364. void Remove();
  365. /// Find child index. Return NINDEX if not found.
  366. i32 FindChild(UIElement* element) const;
  367. /// Set parent element. Same as parent->InsertChild(index, this).
  368. void SetParent(UIElement* parent, i32 index = ENDPOS);
  369. /// Set a user variable.
  370. void SetVar(StringHash key, const Variant& value);
  371. /// Mark as internally (programmatically) created. Used when an element composes itself out of child elements.
  372. /// @property
  373. void SetInternal(bool enable);
  374. /// Set traversal mode for rendering. The default traversal mode is TM_BREADTH_FIRST for non-root element. Root element should be set to TM_DEPTH_FIRST to avoid artifacts during rendering.
  375. /// @property
  376. void SetTraversalMode(TraversalMode traversalMode);
  377. /// Set element event sender flag. When child element is added or deleted, the event would be sent using UIElement found in the parental chain having this flag set. If not set, the event is sent using UI's root as per normal.
  378. /// @property
  379. void SetElementEventSender(bool flag);
  380. /// Set tags. Old tags are overwritten.
  381. void SetTags(const StringVector& tags);
  382. /// Add a tag.
  383. void AddTag(const String& tag);
  384. /// Add tags with the specified separator (; by default).
  385. void AddTags(const String& tags, char separator = ';');
  386. /// Add tags.
  387. void AddTags(const StringVector& tags);
  388. /// Remove specific tag. Return true if existed.
  389. bool RemoveTag(const String& tag);
  390. /// Remove all tags.
  391. void RemoveAllTags();
  392. /// Template version of creating a child element.
  393. template <class T> T* CreateChild(const String& name = String::EMPTY, i32 index = ENDPOS);
  394. /// Template version of returning child element by index using static cast.
  395. template <class T> T* GetChildStaticCast(i32 index) const;
  396. /// Template version of returning child element by name using static cast.
  397. template <class T> T* GetChildStaticCast(const String& name, bool recursive = false) const;
  398. /// Template version of returning child element by variable using static cast. If only key is provided, return the first child having the matching variable key. If value is also provided then the actual variable value would also be checked against.
  399. template <class T> T* GetChildStaticCast(const StringHash& key, const Variant& value = Variant::EMPTY, bool recursive = false) const;
  400. /// Template version of returning child element by index using dynamic cast. May return 0 when casting failed.
  401. template <class T> T* GetChildDynamicCast(i32 index) const;
  402. /// Template version of returning child element by name using dynamic cast. May return 0 when casting failed.
  403. template <class T> T* GetChildDynamicCast(const String& name, bool recursive = false) const;
  404. /// Template version of returning child element by variable. If only key is provided, return the first child having the matching variable key. If value is also provided then the actual variable value would also be checked against using dynamic cast. May return 0 when casting failed.
  405. template <class T> T* GetChildDynamicCast(const StringHash& key, const Variant& value = Variant::EMPTY, bool recursive = false) const;
  406. /// Return name.
  407. /// @property
  408. const String& GetName() const { return name_; }
  409. /// Return position.
  410. /// @property
  411. const IntVector2& GetPosition() const { return position_; }
  412. /// Return size.
  413. /// @property
  414. const IntVector2& GetSize() const { return size_; }
  415. /// Return width.
  416. /// @property
  417. int GetWidth() const { return size_.x_; }
  418. /// Return height.
  419. /// @property
  420. int GetHeight() const { return size_.y_; }
  421. /// Return minimum size.
  422. /// @property
  423. const IntVector2& GetMinSize() const { return minSize_; }
  424. /// Return minimum width.
  425. /// @property
  426. int GetMinWidth() const { return minSize_.x_; }
  427. /// Return minimum height.
  428. /// @property
  429. int GetMinHeight() const { return minSize_.y_; }
  430. /// Return maximum size.
  431. /// @property
  432. const IntVector2& GetMaxSize() const { return maxSize_; }
  433. /// Return minimum width.
  434. /// @property
  435. int GetMaxWidth() const { return maxSize_.x_; }
  436. /// Return minimum height.
  437. /// @property
  438. int GetMaxHeight() const { return maxSize_.y_; }
  439. /// Return true if size is fixed.
  440. /// @property
  441. bool IsFixedSize() const { return minSize_ == maxSize_; }
  442. /// Return true if width is fixed.
  443. /// @property
  444. bool IsFixedWidth() const { return minSize_.x_ == maxSize_.x_; }
  445. /// Return true if height is fixed.
  446. /// @property
  447. bool IsFixedHeight() const { return minSize_.y_ == maxSize_.y_; }
  448. /// Return child element offset.
  449. /// @property
  450. const IntVector2& GetChildOffset() const { return childOffset_; }
  451. /// Return horizontal alignment. If pivot has been adjusted to a custom horizontal setting, returns HA_CUSTOM.
  452. /// @property
  453. HorizontalAlignment GetHorizontalAlignment() const;
  454. /// Return vertical alignment. If pivot has been adjusted to a custom vertical setting, returns VA_CUSTOM.
  455. /// @property
  456. VerticalAlignment GetVerticalAlignment() const;
  457. /// Return whether anchor positioning & sizing is enabled.
  458. /// @property
  459. bool GetEnableAnchor() const { return enableAnchor_; }
  460. /// Return minimum anchor.
  461. /// @property
  462. const Vector2& GetMinAnchor() const { return anchorMin_; }
  463. /// Return maximum anchor.
  464. /// @property
  465. const Vector2& GetMaxAnchor() const { return anchorMax_; }
  466. // Return minimum offset.
  467. /// @property
  468. const IntVector2& GetMinOffset() const { return minOffset_; }
  469. // Return maximum offset.
  470. /// @property
  471. const IntVector2& GetMaxOffset() const { return maxOffset_; }
  472. /// Return pivot.
  473. /// @property
  474. const Vector2& GetPivot() const { return pivot_; }
  475. /// Return child element clipping border.
  476. /// @property
  477. const IntRect& GetClipBorder() const { return clipBorder_; }
  478. /// Return corner color.
  479. /// @property{get_colors}
  480. const Color& GetColor(Corner corner) const { return colors_[corner]; }
  481. /// Return priority.
  482. /// @property
  483. int GetPriority() const { return priority_; }
  484. /// Return opacity.
  485. /// @property
  486. float GetOpacity() const { return opacity_; }
  487. /// Return derived opacity (affected by parent elements). If UseDerivedOpacity is false, returns same as element's own opacity.
  488. /// @property
  489. float GetDerivedOpacity() const;
  490. /// Return whether should be brought to front when focused.
  491. /// @property
  492. bool GetBringToFront() const { return bringToFront_; }
  493. /// Return whether should be put to background when another element is focused.
  494. /// @property
  495. bool GetBringToBack() const { return bringToBack_; }
  496. /// Return whether should clip child elements.
  497. /// @property
  498. bool GetClipChildren() const { return clipChildren_; }
  499. /// Return whether should sort child elements according to priority.
  500. /// @property
  501. bool GetSortChildren() const { return sortChildren_; }
  502. /// Return whether parent elements' opacity affects opacity.
  503. /// @property
  504. bool GetUseDerivedOpacity() const { return useDerivedOpacity_; }
  505. /// Return whether has focus.
  506. /// @property{get_focus}
  507. bool HasFocus() const;
  508. /// Return whether is a direct or indirect child of specified element.
  509. bool IsChildOf(UIElement* element) const;
  510. /// Return whether reacts to input.
  511. /// @property
  512. bool IsEnabled() const { return enabled_; }
  513. /// Returns the element's last own enabled state. May be different than the value returned by IsEnabled when SetDeepEnabled has been used.
  514. /// @property
  515. bool IsEnabledSelf() const { return enabledPrev_; }
  516. /// Return whether value is editable through input.
  517. /// @property
  518. bool IsEditable() const { return editable_; }
  519. /// Return whether is selected. Actual meaning is element dependent.
  520. /// @property
  521. bool IsSelected() const { return selected_; }
  522. /// Return whether element itself should be visible. Elements can be also hidden due to the parent being not visible, use IsVisibleEffective() to check.
  523. /// @property
  524. bool IsVisible() const { return visible_; }
  525. /// Return whether element is effectively visible (parent element chain is visible).
  526. /// @property
  527. bool IsVisibleEffective() const;
  528. /// Return whether the cursor is hovering on this element.
  529. /// @property
  530. bool IsHovering() const { return hovering_; }
  531. /// Return whether is internally created.
  532. /// @property
  533. bool IsInternal() const { return internal_; }
  534. /// Return whether has different color in at least one corner.
  535. /// @property{get_colorGradient}
  536. bool HasColorGradient() const { return colorGradient_; }
  537. /// Return focus mode.
  538. /// @property
  539. FocusMode GetFocusMode() const { return focusMode_; }
  540. /// Return drag and drop flags.
  541. /// @property
  542. DragAndDropModeFlags GetDragDropMode() const { return dragDropMode_; }
  543. /// Return applied style name. Return an empty string when the applied style is an 'auto' style (i.e. style derived from instance's type).
  544. /// @property{get_style}
  545. const String& GetAppliedStyle() const;
  546. /// Return default style.
  547. XMLFile* GetDefaultStyle(bool recursiveUp = true) const;
  548. /// Return layout mode.
  549. /// @property
  550. LayoutMode GetLayoutMode() const { return layoutMode_; }
  551. /// Return layout spacing.
  552. /// @property
  553. int GetLayoutSpacing() const { return layoutSpacing_; }
  554. /// Return layout border.
  555. /// @property
  556. const IntRect& GetLayoutBorder() const { return layoutBorder_; }
  557. /// Return layout flex scale.
  558. /// @property
  559. const Vector2& GetLayoutFlexScale() const { return layoutFlexScale_; }
  560. /// Return number of child elements.
  561. i32 GetNumChildren(bool recursive = false) const;
  562. /// Return child element by index.
  563. /// @property{get_children}
  564. UIElement* GetChild(i32 index) const;
  565. /// Return child element by name.
  566. UIElement* GetChild(const String& name, bool recursive = false) const;
  567. /// Return child element by variable. If only key is provided, return the first child having the matching variable key. If value is also provided then the actual variable value would also be checked against.
  568. UIElement* GetChild(const StringHash& key, const Variant& value = Variant::EMPTY, bool recursive = false) const;
  569. /// Return immediate child elements.
  570. const Vector<SharedPtr<UIElement>>& GetChildren() const { return children_; }
  571. /// Return child elements either recursively or non-recursively.
  572. void GetChildren(Vector<UIElement*>& dest, bool recursive = false) const;
  573. /// Return child elements, optionally recursive.
  574. Vector<UIElement*> GetChildren(bool recursive) const;
  575. /// Return parent element.
  576. /// @property
  577. UIElement* GetParent() const { return parent_; }
  578. /// Return root element.
  579. /// @property
  580. UIElement* GetRoot() const;
  581. /// Return derived color. Only valid when no gradient.
  582. const Color& GetDerivedColor() const;
  583. /// Return a user variable.
  584. const Variant& GetVar(const StringHash& key) const;
  585. /// Return all user variables.
  586. const VariantMap& GetVars() const { return vars_; }
  587. /// Return whether element is tagged by a specific tag.
  588. bool HasTag(const String& tag) const;
  589. /// Return all tags.
  590. /// @property
  591. const StringVector& GetTags() const { return tags_; }
  592. /// Return child elements with a specific tag either recursively or non-recursively.
  593. void GetChildrenWithTag(Vector<UIElement*>& dest, const String& tag, bool recursive = false) const;
  594. /// Return child elements with a specific tag either recursively or non-recursively.
  595. Vector<UIElement*> GetChildrenWithTag(const String& tag, bool recursive = false) const;
  596. /// Return the drag button combo if this element is being dragged.
  597. /// @property
  598. MouseButtonFlags GetDragButtonCombo() const { return dragButtonCombo_; }
  599. /// Return the number of buttons dragging this element.
  600. /// @property
  601. i32 GetDragButtonCount() const { return dragButtonCount_; }
  602. /// Return whether a point (either in element or screen coordinates) is inside the element.
  603. bool IsInside(IntVector2 position, bool isScreen);
  604. /// Return whether a point (either in element or screen coordinates) is inside the combined rect of the element and its children.
  605. bool IsInsideCombined(IntVector2 position, bool isScreen);
  606. /// Return combined screen coordinate rect of element and its children.
  607. /// @property
  608. IntRect GetCombinedScreenRect();
  609. /// Sort child elements if sorting enabled and order dirty. Called by UI.
  610. void SortChildren();
  611. /// Return maximum layout element size in the layout direction. Only valid after layout has been calculated. Used internally by UI for optimizations.
  612. int GetLayoutElementMaxSize() const { return layoutElementMaxSize_; }
  613. /// Return horizontal indentation.
  614. /// @property
  615. int GetIndent() const { return indent_; }
  616. /// Return indent spacing (number of pixels per indentation level).
  617. /// @property
  618. int GetIndentSpacing() const { return indentSpacing_; }
  619. /// Return indent width in pixels.
  620. /// @property
  621. int GetIndentWidth() const { return indent_ * indentSpacing_; }
  622. /// Set child offset.
  623. void SetChildOffset(const IntVector2& offset);
  624. /// Set hovering state.
  625. void SetHovering(bool enable);
  626. /// Adjust scissor for rendering.
  627. void AdjustScissor(IntRect& currentScissor);
  628. /// Get UI rendering batches with a specified offset. Also recurse to child elements.
  629. void GetBatchesWithOffset(IntVector2& offset, Vector<UIBatch>& batches, Vector<float>& vertexData, IntRect currentScissor);
  630. /// Return color attribute. Uses just the top-left color.
  631. const Color& GetColorAttr() const { return colors_[0]; }
  632. /// Return traversal mode for rendering.
  633. /// @property
  634. TraversalMode GetTraversalMode() const { return traversalMode_; }
  635. /// Return whether element should send child added / removed events by itself. If false, defers to parent element.
  636. /// @property
  637. bool IsElementEventSender() const { return elementEventSender_; }
  638. /// Get element which should send child added / removed events.
  639. UIElement* GetElementEventSender() const;
  640. /// Return effective minimum size, also considering layout. Used internally.
  641. IntVector2 GetEffectiveMinSize() const;
  642. /// Set texture to which element will be rendered.
  643. void SetRenderTexture(Texture2D* texture);
  644. protected:
  645. /// Handle attribute animation added.
  646. void OnAttributeAnimationAdded() override;
  647. /// Handle attribute animation removed.
  648. void OnAttributeAnimationRemoved() override;
  649. /// Find target of an attribute animation from object hierarchy by name.
  650. Animatable* FindAttributeAnimationTarget(const String& name, String& outName) override;
  651. /// Mark screen position as needing an update.
  652. void MarkDirty();
  653. /// Remove child XML element by matching attribute name.
  654. bool RemoveChildXML(XMLElement& parent, const String& name) const;
  655. /// Remove child XML element by matching attribute name and value.
  656. bool RemoveChildXML(XMLElement& parent, const String& name, const String& value) const;
  657. /// Filter UI-style attributes in serialization process.
  658. bool FilterUIStyleAttributes(XMLElement& dest, const XMLElement& styleElem) const;
  659. /// Filter implicit attributes in serialization process.
  660. virtual bool FilterImplicitAttributes(XMLElement& dest) const;
  661. /// Update anchored size & position. Only called when anchoring is enabled.
  662. void UpdateAnchoring();
  663. /// Name.
  664. String name_;
  665. /// Child elements.
  666. Vector<SharedPtr<UIElement>> children_;
  667. /// Parent element.
  668. UIElement* parent_{};
  669. /// Child element clipping border.
  670. IntRect clipBorder_;
  671. /// Colors.
  672. Color colors_[MAX_UIELEMENT_CORNERS];
  673. /// User variables.
  674. VariantMap vars_;
  675. /// Priority.
  676. int priority_{};
  677. /// Bring to front when focused flag.
  678. bool bringToFront_{};
  679. /// Bring to back when defocused flag.
  680. bool bringToBack_{true};
  681. /// Clip children flag.
  682. bool clipChildren_{};
  683. /// Sort children according to priority flag.
  684. bool sortChildren_{true};
  685. /// Use derived opacity flag.
  686. bool useDerivedOpacity_{true};
  687. /// Input enabled flag.
  688. bool enabled_{};
  689. /// Last SetEnabled flag before any SetDeepEnabled.
  690. bool enabledPrev_{};
  691. /// Value editable flag.
  692. bool editable_{true};
  693. /// Selected flag.
  694. bool selected_{};
  695. /// Visible flag.
  696. bool visible_{true};
  697. /// Hovering flag.
  698. bool hovering_{};
  699. /// Internally created flag.
  700. bool internal_{};
  701. /// Focus mode.
  702. FocusMode focusMode_{FM_NOTFOCUSABLE};
  703. /// Drag and drop flags.
  704. DragAndDropModeFlags dragDropMode_{DD_DISABLED};
  705. /// Layout mode.
  706. LayoutMode layoutMode_{LM_FREE};
  707. /// Layout spacing.
  708. int layoutSpacing_{};
  709. /// Layout borders.
  710. IntRect layoutBorder_{};
  711. /// Layout flex scale.
  712. Vector2 layoutFlexScale_{Vector2::ONE};
  713. /// Resize nesting level to prevent multiple events and endless loop.
  714. unsigned resizeNestingLevel_{};
  715. /// Layout update nesting level to prevent endless loop.
  716. unsigned layoutNestingLevel_{};
  717. /// Layout element maximum size in layout direction.
  718. int layoutElementMaxSize_{};
  719. /// Horizontal indentation.
  720. int indent_{};
  721. /// Indent spacing (number of pixels per indentation level).
  722. int indentSpacing_{16};
  723. /// Position.
  724. IntVector2 position_{};
  725. /// Screen position.
  726. mutable IntVector2 screenPosition_;
  727. /// Screen position dirty flag.
  728. mutable bool positionDirty_{true};
  729. /// Applied style.
  730. String appliedStyle_;
  731. /// Drag button combo.
  732. MouseButtonFlags dragButtonCombo_{};
  733. /// Drag button count.
  734. i32 dragButtonCount_{};
  735. private:
  736. /// Return child elements recursively.
  737. void GetChildrenRecursive(Vector<UIElement*>& dest) const;
  738. /// Return child elements with a specific tag recursively.
  739. void GetChildrenWithTagRecursive(Vector<UIElement*>& dest, const String& tag) const;
  740. /// Recursively apply style to a child element hierarchy when adding to an element.
  741. void ApplyStyleRecursive(UIElement* element);
  742. /// Calculate layout width for resizing the parent element.
  743. int CalculateLayoutParentSize(const Vector<int>& sizes, int begin, int end, int spacing);
  744. /// Calculate child widths/positions in the layout.
  745. void CalculateLayout
  746. (Vector<int>& positions, Vector<int>& sizes, const Vector<int>& minSizes, const Vector<int>& maxSizes,
  747. const Vector<float>& flexScales, int targetSize, int begin, int end, int spacing);
  748. /// Get child element constant position in a layout.
  749. IntVector2 GetLayoutChildPosition(UIElement* child);
  750. /// Detach from parent.
  751. void Detach();
  752. /// Verify that child elements have proper alignment for layout mode.
  753. void VerifyChildAlignment();
  754. /// Handle logic post-update event.
  755. void HandlePostUpdate(StringHash eventType, VariantMap& eventData);
  756. /// Size.
  757. IntVector2 size_;
  758. /// Minimum size.
  759. IntVector2 minSize_;
  760. /// Maximum size.
  761. IntVector2 maxSize_{M_MAX_INT, M_MAX_INT};
  762. /// Child elements' offset. Used internally.
  763. IntVector2 childOffset_;
  764. /// Parent's minimum size calculated by layout. Used internally.
  765. IntVector2 layoutMinSize_;
  766. /// Minimum offset.
  767. IntVector2 minOffset_;
  768. /// Maximum offset.
  769. IntVector2 maxOffset_;
  770. /// Use min/max anchor & min/max offset for position & size instead of setting explicitly.
  771. bool enableAnchor_{};
  772. /// Has pivot changed manually.
  773. bool pivotSet_{};
  774. /// Anchor minimum position.
  775. Vector2 anchorMin_;
  776. /// Anchor maximum position.
  777. Vector2 anchorMax_;
  778. /// Pivot Position.
  779. Vector2 pivot_;
  780. /// Opacity.
  781. float opacity_{1.0f};
  782. /// Derived opacity.
  783. mutable float derivedOpacity_{};
  784. /// Derived color. Only valid when no gradient.
  785. mutable Color derivedColor_;
  786. /// Derived opacity dirty flag.
  787. mutable bool opacityDirty_{true};
  788. /// Derived color dirty flag (only used when no gradient).
  789. mutable bool derivedColorDirty_{true};
  790. /// Child priority sorting dirty flag.
  791. bool sortOrderDirty_{};
  792. /// Has color gradient flag.
  793. bool colorGradient_{};
  794. /// Default style file.
  795. SharedPtr<XMLFile> defaultStyle_;
  796. /// Last applied style file.
  797. WeakPtr<XMLFile> appliedStyleFile_;
  798. /// Traversal mode for rendering.
  799. TraversalMode traversalMode_{TM_BREADTH_FIRST};
  800. /// Flag whether node should send child added / removed events by itself.
  801. bool elementEventSender_{};
  802. /// XPath query for selecting UI-style.
  803. static XPathQuery styleXPathQuery_;
  804. /// Tag list.
  805. StringVector tags_;
  806. };
  807. template <class T> T* UIElement::CreateChild(const String& name, i32 index/* = ENDPOS*/)
  808. {
  809. assert(index >= 0 || index == ENDPOS);
  810. return static_cast<T*>(CreateChild(T::GetTypeStatic(), name, index));
  811. }
  812. template <class T> T* UIElement::GetChildStaticCast(i32 index) const
  813. {
  814. assert(index >= 0);
  815. return static_cast<T*>(GetChild(index));
  816. }
  817. template <class T> T* UIElement::GetChildStaticCast(const String& name, bool recursive) const
  818. {
  819. return static_cast<T*>(GetChild(name, recursive));
  820. }
  821. template <class T> T* UIElement::GetChildStaticCast(const StringHash& key, const Variant& value, bool recursive) const
  822. {
  823. return static_cast<T*>(GetChild(key, value, recursive));
  824. }
  825. template <class T> T* UIElement::GetChildDynamicCast(i32 index) const
  826. {
  827. assert(index >= 0);
  828. return dynamic_cast<T*>(GetChild(index));
  829. }
  830. template <class T> T* UIElement::GetChildDynamicCast(const String& name, bool recursive) const
  831. {
  832. return dynamic_cast<T*>(GetChild(name, recursive));
  833. }
  834. template <class T> T* UIElement::GetChildDynamicCast(const StringHash& key, const Variant& value, bool recursive) const
  835. {
  836. return dynamic_cast<T*>(GetChild(key, value, recursive));
  837. }
  838. }